Skip to content

Commit

Permalink
Merge pull request #9 from lsd-ucsc/dev
Browse files Browse the repository at this point in the history
Build against latest solc and ganache
  • Loading branch information
zhenghaven authored Aug 25, 2023
2 parents e787a2c + 3f876ea commit 565ddae
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 6 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/create-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
python-version: [ 3.11 ]
node-version: [ 18.16.0 ]

ganache-version: [ 7.8.0 ]
ganache-version: [ 7.9.1 ]

solc-version: [ v0.8.20 ]
solc-version: [ v0.8.21 ]

env:
SOLC_BIN: ${{ github.workspace }}/build/solc-static-linux
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pubsub-solidity-unittesting.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
os: [ ubuntu-22.04 ]
solc-version: [ 0.8.20 ]
solc-version: [ 0.8.21 ]
chain-fork: [ shanghai ]
opt-runs: [ 200 ]

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MODULES := \
PubSub \
tests
SOLC_VERSION := v0.8.20
SOLC_VERSION := v0.8.21
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(dir $(MKFILE_PATH))
SOLC_BIN := $(CURRENT_DIR)/build/solc-static-linux
Expand Down
63 changes: 63 additions & 0 deletions tests/BasicActionGasCost.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.17 <0.9.0;


contract GasEvalSubscriber {
constructor() {
}

function onNotify(bytes memory data) external {
// do nothing
}
}


contract BasicActionGasCost {

event LogGasCost(uint8 idx, uint256 gasUsed);

address m_subAddr = address(0);
bool m_someBool = false;
mapping(address => bool) m_someMap;
address m_someAddr = 0x0000000000000000000000000000000000000000;

constructor() {
GasEvalSubscriber sub = new GasEvalSubscriber();
m_subAddr = address(sub);

m_someMap[m_someAddr] = true;
}

function eval() external {
bytes memory data = new bytes(0);

uint256 gasStart = 0;
uint256 gasUsed = 0;
bool someBool = !m_someBool;
address someAddr = msg.sender;
address someAddr2 = m_someAddr;

gasStart = gasleft();
GasEvalSubscriber(m_subAddr).onNotify(data);
gasUsed = gasStart - gasleft();
emit LogGasCost(1, gasUsed);

gasStart = gasleft();
m_someBool = someBool;
gasUsed = gasStart - gasleft();
emit LogGasCost(2, gasUsed);

gasStart = gasleft();
m_someMap[someAddr] = someBool;
gasUsed = gasStart - gasleft();
emit LogGasCost(3, gasUsed);

gasStart = gasleft();
delete m_someMap[someAddr2];
gasUsed = gasStart - gasleft();
emit LogGasCost(4, gasUsed);

m_someBool = false;
m_someMap[someAddr2] = true;
}
}
3 changes: 2 additions & 1 deletion tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
MODULE_NAME := tests
CONTRACTS := \
HelloWorldPublisher \
HelloWorldSubscriber
HelloWorldSubscriber \
BasicActionGasCost

MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(dir $(MKFILE_PATH))
Expand Down
172 changes: 172 additions & 0 deletions utils/GanacheBasicActionTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
###
# Copyright (c) 2023 Roy Shadmon, Haofan Zheng
# Use of this source code is governed by an MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT.
###


import logging
import os
import signal
import subprocess
import sys
import time

from typing import List
from web3 import Web3


BASE_DIR_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BUILD_DIR_PATH = os.path.join(BASE_DIR_PATH, 'build')
UTILS_DIR_PATH = os.path.join(BASE_DIR_PATH, 'utils')
PYHELPER_DIR = os.path.join(UTILS_DIR_PATH, 'PyEthHelper')
PROJECT_CONFIG_PATH = os.path.join(UTILS_DIR_PATH, 'project_conf.json')
CHECKSUM_KEYS_PATH = os.path.join(BUILD_DIR_PATH, 'ganache_keys_checksum.json')
GANACHE_KEYS_PATH = os.path.join(BUILD_DIR_PATH, 'ganache_keys.json')
GANACHE_PORT = 7545
NUM_OF_ACCOUNTS = 100
GANACHE_NET_ID = 1337


sys.path.append(PYHELPER_DIR)
from PyEthHelper import EthContractHelper
from PyEthHelper import GanacheAccounts


def StartGanache() -> subprocess.Popen:
cmd = [
'ganache-cli',
'-p', str(GANACHE_PORT),
'-d',
'-a', str(NUM_OF_ACCOUNTS),
'--network-id', str(GANACHE_NET_ID),
'--chain.hardfork', 'shanghai',
'--wallet.accountKeysPath', str(GANACHE_KEYS_PATH),
]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

return proc


def ReadEvalLogEvents(logs: List[dict]) -> None:
for log in logs:
if (
(len(log['topics']) > 0) and
(
log['topics'][0].hex() ==
'0xe1ae46340cc3bb84afacee6678b86b538a6d5e4ce754adb3bfa9ce4e41d196ba'
)
):
hexData = log['data'].hex()
assert len(hexData) == 2 + (2 * (32 + 32)), 'Invalid log data length'
bData = bytes.fromhex(hexData[2:])
idx = int.from_bytes(bData[:32], byteorder='big')
gasUsed = int.from_bytes(bData[32:], byteorder='big')
print(f'Evaluated action at index {idx} with gas used {gasUsed}')


def RunTests() -> dict:
# connect to ganache
ganacheUrl = 'http://localhost:{}'.format(GANACHE_PORT)
w3 = Web3(Web3.HTTPProvider(ganacheUrl))
while not w3.is_connected():
print('Attempting to connect to ganache...')
time.sleep(1)
print('Connected to ganache')

# checksum keys
GanacheAccounts.ChecksumGanacheKeysFile(
CHECKSUM_KEYS_PATH,
GANACHE_KEYS_PATH
)

# setup account
privKey = EthContractHelper.SetupSendingAccount(
w3=w3,
account=0,
keyJson=CHECKSUM_KEYS_PATH
)

# deploy BasicActionGasCost contract
print('Deploying BasicActionGasCost contract...')
baContract = EthContractHelper.LoadContract(
w3=w3,
projConf=PROJECT_CONFIG_PATH,
contractName='BasicActionGasCost',
release=None, # use locally built contract
address=None, # deploy new contract
)
baReceipt = EthContractHelper.DeployContract(
w3=w3,
contract=baContract,
arguments=[ ],
privKey=privKey,
gas=None, # let web3 estimate
value=0,
confirmPrompt=False # don't prompt for confirmation
)
baAddr = baReceipt.contractAddress
print('BasicActionGasCost contract deployed at {}'.format(baAddr))

# load deployed BasicActionGasCost contract
baContract = EthContractHelper.LoadContract(
w3=w3,
projConf=PROJECT_CONFIG_PATH,
contractName='BasicActionGasCost',
release=None, # use locally built contract
address=baAddr, # use deployed contract
)

evalTxReceipt = EthContractHelper.CallContractFunc(
w3=w3,
contract=baContract,
funcName='eval',
arguments=[ ],
privKey=privKey,
gas=None, # let web3 estimate
value=0,
confirmPrompt=False # don't prompt for confirmation
)
ReadEvalLogEvents(evalTxReceipt.logs)


def StopGanache(ganacheProc: subprocess.Popen) -> None:
print('Shutting down ganache (it may take ~15 seconds)...')
waitEnd = time.time() + 20
ganacheProc.terminate()
while ganacheProc.poll() is None:
try:
if time.time() > waitEnd:
print('Force to shut down ganache')
ganacheProc.kill()
else:
print('Still waiting for ganache to shut down...')
ganacheProc.send_signal(signal.SIGINT)
ganacheProc.wait(timeout=2)
except subprocess.TimeoutExpired:
continue
print('Ganache has been shut down')


def main():
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(name)s %(message)s'
)

ganacheProc = StartGanache()

try:
RunTests()

finally:
# finish and exit
StopGanache(ganacheProc)


if __name__ == "__main__":
main()

3 changes: 2 additions & 1 deletion utils/project_conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"PubSubService" : "PubSub",
"EventManager" : "PubSub",
"HelloWorldPublisher" : "tests",
"HelloWorldSubscriber": "tests"
"HelloWorldSubscriber": "tests",
"BasicActionGasCost" : "tests"
},
"releaseUrl": "https://github.com/lsd-ucsc/decent-pubsub-onchain/releases/download/{version}/{contract}",
"buildDir" : "build"
Expand Down

0 comments on commit 565ddae

Please sign in to comment.