diff --git a/build.gradle b/build.gradle index 58da8e9..5a8c585 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ println("Notice: current gradle version is " + gradle.gradleVersion) // Additional attribute definition ext { // jackson version - javaSDKVersion="3.7.0-SNAPSHOT" + javaSDKVersion="3.7.0" //solcJVersion = "0.4.25.1" //solcJVersion = "0.5.2.1" //solcJVersion = "0.6.10.1" diff --git a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/AnonymousVotingInterface.sol b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/AnonymousVotingInterface.sol new file mode 100644 index 0000000..59b9e2e --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/AnonymousVotingInterface.sol @@ -0,0 +1,101 @@ +// Copyright (C) @2014-2022 Webank +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.6.10 <0.8.20; +pragma experimental ABIEncoderV2; + +import "./ZkpPrecompiled.sol"; +import "./WedprUtils.sol"; +import "./Crypto.sol"; + + struct SystemParameters { + int256 itemId; // the itemId + string itemMeta; // item meta data + string[] candidates; + bytes hpoint; + } + + struct Ballot{ + string candidateId; + bytes cipher1; + bytes cipher2; + bool isAssigned; + } +// the ballot proof + struct BallotProof{ + bytes formatProof; + bytes eitherEqualityProof; + Ballot ballot; + } + + struct UnlistedBallot + { + bytes cipher1; + bytes cipher2; + Ballot ballot; + bool isAssigned; + } +// the candiate ballot proof + struct UnlistedCandidateBallotProof + { + UnlistedBallot ballot; + BallotProof unlisted_ballot_proof; + } + struct VoteRequest{ + Ballot blankBallot; + Ballot zeroBallot; + // bytes publicKey; + // bytes32 signatureR; + // bytes32 signatureS; + } + struct VoteStorage{ + bool isAssigned; + VoteRequest voteRequest; + string[] candidateListForBallot; + bytes[] cipherCandidateListForUnlistedBallot; + } + struct CounterStorage + { + // 计票公钥分片 + bytes hpointShare; + // 计票公钥是否被聚合 + bool setted; + // 计票服务状态,1:计票中,2:计票完成 + int8 counterStatus; + // 计票服务实例的心跳时间 + uint256 updateTime; + // 一个投票item中投票密文的聚合值 + string voteStorageSum; + // 使用acv-core的公钥加密的计票服务sm4密钥 + string sm4SecretKeyCipherText; + // 使用计票服务的sm4密钥加密的计票分片 + string countingPartResultCipherText; + // 计票分片哈希值 + bytes decryptedPartResultHash; + } + +contract AnonymousVotingInterface { + function initialize(bytes memory basePointG1, bytes memory basePointG2) public virtual; + function setSystemParameters(int256 itemId, string memory itemMeta, string[] memory candidates, bytes memory hpoint) public virtual; + function getSystemParameters() public view virtual returns(SystemParameters memory); + function setCounterNumber(uint256 counterNumber) public virtual; + function getCounterNumber() public view virtual returns(uint256); + function setContractState(uint8 state) public virtual; + function getContractState() public view virtual returns(uint8); + function setVoterIdList(string[] memory voterIdList) public virtual; + function getVoterIdList() public view virtual returns(string[] memory); + function setVoterIdToVoteStorage(string memory voterId, VoteStorage memory voteStorage) public virtual; + function getVoterIdToVoteStorage(string memory voterId) public view virtual returns(VoteStorage memory); + function setVoterIDToCandidateIDToBallot(string memory voterId, string memory candidateId, Ballot memory ballot) public virtual; + function getVoterIDToCandidateIDToBallot(string memory voterId, string memory candidateId) public view virtual returns(Ballot memory); + function setVoterIDToCandidateIDToUnlistedBallot(string memory voterId, bytes memory candidateId, UnlistedBallot memory unlistedBallot) public virtual; + function getVoterIDToCandidateIDToUnlistedBallot(string memory voterId, bytes memory candidateId) public view virtual returns(UnlistedBallot memory); + function setCounterIdToCounterStorage(string memory counterId, CounterStorage memory counterStorage) public virtual; + function getCounterIdToCounterStorage(string memory counterId) public view virtual returns(CounterStorage memory); + function setCounterStatus(string memory counterId, int8 status) public virtual; + function getCounterStatus(string memory counterId) public view virtual returns(int8); + function setCounterUpdateTime(string memory counterId, uint256 updateTime) public virtual; + function getCounterUpdateTime(string memory counterId) public view virtual returns(uint256); + function setVoteStorageSum(string memory counterId, string memory voteStorageSum) public virtual; + function getVoteStorageSum(string memory counterId) public view virtual returns(string memory); + function setSm4SecretKeyCipherText(string memory counterId, string memory sm4SecretKeyCipherText) public virtual; +} diff --git a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/BalanceReceiveTest.sol b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/BalanceReceiveTest.sol new file mode 100644 index 0000000..7c54281 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/BalanceReceiveTest.sol @@ -0,0 +1,163 @@ +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +contract ReceiveAndCallbackFunction { + event Info(string, uint256); + // receive function + receive() external payable { + require(msg.value > 10, "receive() msg.value is zero"); + emit Info("receive() msg.value", msg.value); + } + + // fallback function + fallback() external payable { + require(msg.value > 0, "fallback() msg.value is zero"); + emit Info("fallback() msg.value", msg.value); + } +} + +contract OnlyReceiveFunction { + event Info(string, uint256); + // receive function + receive() external payable { + require(msg.value > 10, "receive() msg.value is zero"); + emit Info("receive() msg.value", msg.value); + } +} + +contract OnlyFallbackFunction { + + event Info(string, uint256); + + // fallback function + fallback() external payable { + require(msg.value > 0, "fallback() msg.value is zero"); + emit Info("fallback() msg.value", msg.value); + } +} + + +contract BalanceReceiveTest { + modifier mustHasBalance() { + require(address(this).balance > 0, "balance not enough"); + _; + } + + function callTransfer(address payable to, uint256 amount) public payable { + to.transfer(amount); + } + + function callFallback(address payable to, uint256 amount) public payable { + (bool success, bytes memory reason) = to.call{value: amount}("aaa()"); + require(success, string(abi.encodePacked("callFallback failed: ", reason))); + } + + function checkOnlyFallbackFunction() public payable { + uint256 callValue = 7; + + OnlyFallbackFunction contractAddress = new OnlyFallbackFunction(); + // must success + try this.callTransfer(address(contractAddress), callValue) { + } catch (bytes memory reason) { + require(false, string(abi.encodePacked("checkOnlyFallbackFunction callTransfer with value failed: ", reason))); + } + + require(address(contractAddress).balance == callValue, "checkReceive failed: balance not equal"); + + // must failed transfer 0 + try this.callTransfer(address(contractAddress), 0) { + require(false, "checkOnlyFallbackFunction callTransfer without value should revert"); + } catch { + } + + // must success on fallback value is not 0 + try this.callFallback(address(contractAddress), callValue) { + } catch (bytes memory reason) { + require(false, string(abi.encodePacked("checkOnlyFallbackFunction callFallback with value failed: ", reason))); + } + + require(address(contractAddress).balance == callValue * 2, "checkReceive failed: balance not equal"); + + // must failed on fallback value is 0 + try this.callFallback(address(contractAddress), 0) { + require(false, "checkOnlyFallbackFunction callFallback without value should revert"); + } catch { + } + } + + function checkOnlyReceiveFunction() public payable { + uint256 callValue = 17; + + OnlyReceiveFunction contractAddress = new OnlyReceiveFunction(); + // must success + try this.callTransfer(address(contractAddress), callValue) { + } catch (bytes memory reason) { + require(false, string(abi.encodePacked("checkOnlyReceiveFunction callTransfer with value failed: ", reason))); + } + + require(address(contractAddress).balance == callValue, "checkReceive failed: balance not equal"); + + // must failed transfer lesser than 10 + try this.callTransfer(address(contractAddress), 1) { + require(false, "checkOnlyReceiveFunction callTransfer without value should revert"); + } catch { + } + + // must failed on fallback value is over 10 + try this.callFallback(address(contractAddress), callValue) { + require(false, "checkOnlyReceiveFunction callFallback with value should revert"); + } catch { + } + + require(address(contractAddress).balance == callValue, "checkReceive failed: balance not equal"); + + // must failed on fallback value is lesser than 10 + try this.callFallback(address(contractAddress), 1) { + require(false, "checkOnlyReceiveFunction callFallback without value should revert"); + } catch { + } + } + + function checkReceiveAndFallbackFunction() public payable { + uint256 callValue = 17; + ReceiveAndCallbackFunction contractAddress = new ReceiveAndCallbackFunction(); + // must success + try this.callTransfer(address(contractAddress), callValue) { + } catch (bytes memory reason) { + require(false, string(abi.encodePacked("checkReceiveAndFallbackFunction callTransfer with value failed: ", reason))); + } + + require(address(contractAddress).balance == callValue, "checkReceive failed: balance not equal"); + + // must failed transfer 0 + try this.callTransfer(address(contractAddress), 1) { + require(false, "checkReceiveAndFallbackFunction callTransfer without value should revert"); + } catch { + } + require(address(contractAddress).balance == callValue, "checkReceive failed: balance not equal"); + + uint256 callValue2 = 5; + + // must success on fallback value is not 0 + try this.callFallback(address(contractAddress), callValue2) { + } catch (bytes memory reason) { + require(false, string(abi.encodePacked("checkReceiveAndFallbackFunction callFallback with value failed: ", reason))); + } + + require(address(contractAddress).balance == callValue + callValue2, "checkReceive failed: balance not equal"); + + // must failed on fallback value is 0 + try this.callFallback(address(contractAddress), 0) { + require(false, "checkReceiveAndFallbackFunction callFallback without value should revert"); + } catch { + } + + require(address(contractAddress).balance == callValue + callValue2, "checkReceive failed2: balance not equal"); + } + + function check() public payable mustHasBalance { + checkOnlyFallbackFunction(); + checkOnlyReceiveFunction(); + checkReceiveAndFallbackFunction(); + } +} \ No newline at end of file diff --git a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/BalanceTest.sol b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/BalanceTest.sol index 2684e73..207e585 100644 --- a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/BalanceTest.sol +++ b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/BalanceTest.sol @@ -91,7 +91,6 @@ contract BalanceTest { } } - return; // foreach errorAddresses for (uint256 i = 0; i < errorAddresses.length; i++) { address payable addr = errorAddresses[i]; @@ -115,6 +114,19 @@ contract BalanceTest { require(balanceBeforeSelf - balanceAfterSelf == 1, "self balance should be decreased by amount"); } + event Info2(string info, address addr, uint256 value); + function testTransferBalanceToOrigin() public mustHasBalance { + uint256 balanceBefore = getBalance(tx.origin); + uint256 balanceBeforeSelf = getSelfBalance(); + address payable origin = payable(tx.origin); + origin.transfer(1); + uint256 balanceAfter = getBalance(tx.origin); + uint256 balanceAfterSelf = getSelfBalance(); + require(balanceAfter - balanceBefore == 1, "balance should be increased by amount"); + require(balanceBeforeSelf - balanceAfterSelf == 1, "self balance should be decreased by amount"); + Info2("testTransferBalanceToOrigin", tx.origin, balanceAfter); + } + function testSelfdestruct() public payable { uint256 balanceBefore = getBalance(msg.sender); uint256 balanceBeforeSelf = getSelfBalance(); @@ -168,15 +180,14 @@ contract BalanceTest { testCallNotPayableWithValue(); testDeployWithValue(); testTransferBalance(); + testTransferBalanceToOrigin(); testBaseFee(); testGasPrice(); testMsgValue(); + testTransferBalanceToPrecompiled(); testSelfdestruct(); - - //testSelfdestructZeroAddress(); - //testDeployNotPayableWithValue() - //testTransferBalanceToPrecompiled(); + /* testTransferIndelegateCall check sender testTransferToPrecompiledIndelegateCall testTransferBalance(); diff --git a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/ContractTestAll.sol b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/ContractTestAll.sol index 0d84374..ffa9588 100644 --- a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/ContractTestAll.sol +++ b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/ContractTestAll.sol @@ -11,25 +11,26 @@ import "./ECRecoverTest.sol"; import "./DeployTreeTest.sol"; // DMC import "./BalanceTest.sol"; import "./BalancePrecompiledTest.sol"; +import "./BalanceReceiveTest.sol"; contract ContractTestAll { + event Info(string, uint256, uint256); function checkOne(string memory name, address addr, bool needProxyCheck, uint256 callValue) private { + uint256 gasBefore = gasleft(); + (bool success, bytes memory reason) = address(addr).call{value: callValue}(abi.encodeWithSignature("check()")); + require(success, string(abi.encodePacked(name, " check failed: ", reason))); - try ContractTestAll(addr).check{value: callValue}() { // just a little trick to call check() in the target contract - // success - } catch (bytes memory reason) { - revert(string(abi.encodePacked(name, " check failed: ", reason))); - } + uint256 gasBeforeProxy = gasleft(); - if (!needProxyCheck) { - return; + if (needProxyCheck) { + // use proxy to call check() + Proxy proxy = new ProxyImpl(addr); + (success, reason) = address(proxy).call{value: callValue}(abi.encodeWithSignature("check()")); + require(success, string(abi.encodePacked(name, " proxy check failed: ", reason))); } - - // use proxy to call check() - Proxy proxy = new ProxyImpl(addr); - (bool success, bytes memory reason) = address(proxy).call{value: callValue}(abi.encodeWithSignature("check()")); - require(success, string(abi.encodePacked(name, " proxy check failed: ", reason))); + uint256 gasAfter = gasleft(); + emit Info(string(abi.encodePacked(name, " gas used ")), gasBefore - gasBeforeProxy, gasBeforeProxy - gasAfter); } function check() public payable { @@ -43,11 +44,16 @@ contract ContractTestAll { checkOne("EventTest", address(new EventTest()), true, 0); checkOne("LibraryTest", address(new LibraryTest()), true, 0); checkOne("ProxyTest", address(new ProxyTest()), true, 0); - //checkOne("StaticCall", address(new StaticCall()), true, 0); checkOne("TablePrecompiledTest", address(new TablePrecompiledTest()), true, 0); checkOne("ECRecoverTest", address(new ECRecoverTest()), true, 0); checkOne("DeployTreeTest", address(new DeployTreeTest()), true, 0); // DMC checkOne("BalanceTest", address(new BalanceTest()), true, callValue); checkOne("BalancePrecompiledTest", address(new BalancePrecompiledTest()), false, 0); + checkOne("BalanceReceiveTest", address(new BalanceReceiveTest()), true, callValue); + + checkOne("StaticCall", address(new StaticCall()), false, 0); // must at last for gas will be used up by staticcall failed } + + // fallback + fallback() external payable {} } diff --git a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/StaticCall.sol b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/StaticCall.sol index 7e43736..88f34e6 100644 --- a/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/StaticCall.sol +++ b/src/main/java/org/fisco/bcos/sdk/demo/contract/sol/StaticCall.sol @@ -1,5 +1,7 @@ pragma solidity >=0.6.0 <0.8.12; +import "./ProxyTest.sol"; + contract StaticCall { HelloWorld helloWorld = new HelloWorld(); event Result(bytes); @@ -82,22 +84,50 @@ contract StaticCall { function testEmptyAddr() public { (bool ok, bytes memory result) = address(0x10016666666).staticcall(abi.encodeWithSignature("get()")); require(ok, "addr not exist but must return ok to be the same as eth"); + require(result.length == 0, "result must be empty"); } - function check() public initIfNot { + function checkOk() public initIfNot { (bool ok, bytes memory result) = address(helloWorld).staticcall(abi.encodeWithSignature("get()")); require(ok); - (ok, result) = address(helloWorld).staticcall(abi.encodeWithSignature("set(string)", "aaa")); - require(!ok, "staticcall a state write function must return not ok"); + testASMOk(); + } + function checkFailed() public { testEmptyAddr(); - testASMOk(); + (bool ok, bytes memory result) = address(helloWorld).staticcall(abi.encodeWithSignature("set(string)", "aaa")); + require(!ok, "staticcall a state write function must return not ok"); + require(result.length == 0, string(abi.encodePacked("staticcall failed for has result: ", result))); + testASMFailed(); testASMUintFailed(); } + event Info(string, uint256); + function check() public { + uint256 gasBefore = gasleft(); + checkOk(); + uint256 gasAfter = gasleft(); + emit Info("gas used on checkOk(): ", gasBefore - gasAfter); + + Proxy proxy = new ProxyImpl(address(this)); + gasBefore = gasleft(); + (bool success, bytes memory reason) = address(proxy).call(abi.encodeWithSignature("checkOk()")); + gasAfter = gasleft(); + require(success, string(abi.encodePacked("checkOk() by proxy failed: ", reason))); + emit Info("gas used on checkOk() by proxy: ", gasBefore - gasAfter); + + // staticcall failed will cost half of the gas + // There are many staticcall failed in checkFailed(), will cost most of the gas. So we need to put it in the end. + gasBefore = gasleft(); + (success, reason) = address(proxy).call(abi.encodeWithSignature("checkFailed()")); + gasAfter = gasleft(); + require(success, string(abi.encodePacked("checkFailed() by proxy failed: ", reason))); + emit Info("gas used on checkFailed() by proxy: ", gasBefore - gasAfter); + } + function get() public view returns (string memory) { return helloWorld.get(); }