mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Implement new with CREATE2 and function call options.
This commit is contained in:
committed by
chriseth
parent
679f729f2f
commit
a3f23d3158
@@ -1929,6 +1929,40 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic)
|
||||
BOOST_REQUIRE(callContractFunction("checkState()") == encodeArgs(false, 20 - 5));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(gas_and_value_brace_syntax)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract helper {
|
||||
bool flag;
|
||||
function getBalance() payable public returns (uint256 myBalance) {
|
||||
return address(this).balance;
|
||||
}
|
||||
function setFlag() public { flag = true; }
|
||||
function getFlag() public returns (bool fl) { return flag; }
|
||||
}
|
||||
contract test {
|
||||
helper h;
|
||||
constructor() public payable { h = new helper(); }
|
||||
function sendAmount(uint amount) public payable returns (uint256 bal) {
|
||||
return h.getBalance{value: amount}();
|
||||
}
|
||||
function outOfGas() public returns (bool ret) {
|
||||
h.setFlag{gas: 2}(); // should fail due to OOG
|
||||
return true;
|
||||
}
|
||||
function checkState() public returns (bool flagAfter, uint myBal) {
|
||||
flagAfter = h.getFlag();
|
||||
myBal = address(this).balance;
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 20);
|
||||
BOOST_REQUIRE(callContractFunction("sendAmount(uint256)", 5) == encodeArgs(5));
|
||||
// call to helper should not succeed but amount should be transferred anyway
|
||||
BOOST_REQUIRE(callContractFunction("outOfGas()") == bytes());
|
||||
BOOST_REQUIRE(callContractFunction("checkState()") == encodeArgs(false, 20 - 5));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(gasleft_decrease)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
contract D {}
|
||||
contract C {
|
||||
function foo(int a) payable external {
|
||||
this.foo{gas:2, gas: 5};
|
||||
this.foo{value:2, value: 5};
|
||||
this.foo{gas:2, value: 5, gas:2, value:3};
|
||||
new D{salt:"abc", salt:"efg"}();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// TypeError: (78-101): Duplicate option "gas".
|
||||
// TypeError: (111-138): Duplicate option "value".
|
||||
// TypeError: (148-189): Duplicate option "gas".
|
||||
// TypeError: (148-189): Duplicate option "value".
|
||||
// TypeError: (199-228): Duplicate option "salt".
|
||||
@@ -0,0 +1,8 @@
|
||||
contract C {
|
||||
function foo() pure internal {
|
||||
address(10).delegatecall{value: 7, gas: 3}("");
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (56-98): Cannot set option "value" for delegatecall.
|
||||
// Warning: (56-102): Return value of low-level calls not used.
|
||||
@@ -0,0 +1,8 @@
|
||||
contract D {}
|
||||
contract C {
|
||||
function foo(int a) pure internal {
|
||||
foo{gas: 5};
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (75-86): Function call options can only be set on external function calls or contract creations.
|
||||
@@ -0,0 +1,21 @@
|
||||
contract D {}
|
||||
contract C {
|
||||
function foo(int a) payable external {
|
||||
this.foo{value:2, gas: 5}{gas:2};
|
||||
(this.foo{value:2, gas: 5}){gas:2};
|
||||
this.foo{value:2, gas: 5}{value:6};
|
||||
this.foo.value(4){value:2, gas: 5};
|
||||
this.foo{gas:2, value: 5}{value:2, gas:5};
|
||||
new D{salt:"abc"}{salt:"a"}();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// TypeError: (78-110): Option "gas" has already been set.
|
||||
// TypeError: (120-154): Option "gas" has already been set.
|
||||
// TypeError: (164-198): Option "value" has already been set.
|
||||
// TypeError: (208-242): Option "value" has already been set.
|
||||
// TypeError: (252-293): Option "value" has already been set.
|
||||
// TypeError: (252-293): Option "gas" has already been set.
|
||||
// TypeError: (303-330): Option "salt" has already been set.
|
||||
@@ -0,0 +1,8 @@
|
||||
contract D {}
|
||||
contract C {
|
||||
function foo(int a) pure internal {
|
||||
a{val:5};
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (71-79): Expected callable expression before call options.
|
||||
@@ -0,0 +1,8 @@
|
||||
contract D {}
|
||||
contract C {
|
||||
function foo(int a) pure external {
|
||||
this.foo{random:5+5};
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (73-93): Unknown call option "random". Valid options are "salt", "value" and "gas".
|
||||
@@ -0,0 +1,10 @@
|
||||
contract D {}
|
||||
contract C {
|
||||
function foo(int a) external {
|
||||
this.foo{slt:5, value:3, salt: 8};
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (64-97): Unknown call option "slt". Valid options are "salt", "value" and "gas".
|
||||
// TypeError: (64-97): Cannot set option "value" on a non-payable function type.
|
||||
// TypeError: (64-97): Function call option "salt" can only be used with "new".
|
||||
@@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function foo() internal {
|
||||
(bool success, ) = address(10).call{value: 7, gas: 3}("");
|
||||
success;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
@@ -0,0 +1,12 @@
|
||||
contract D { constructor() public payable {} }
|
||||
contract C {
|
||||
function foo() pure internal {
|
||||
new D{salt:"abc", value:3};
|
||||
new D{salt:"abc"};
|
||||
new D{value:5+5};
|
||||
new D{salt:"aabbcc"};
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
@@ -0,0 +1,15 @@
|
||||
contract D { constructor() public payable {} }
|
||||
contract C {
|
||||
function foo() pure internal {
|
||||
new D{salt:"abc", value:3};
|
||||
new D{salt:"abc"};
|
||||
new D{value:5+5};
|
||||
new D{salt:"aabbcc"};
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: <constantinople
|
||||
// ----
|
||||
// TypeError: (97-123): Unsupported call option "salt" (requires Constantinople-compatible VMs).
|
||||
// TypeError: (127-144): Unsupported call option "salt" (requires Constantinople-compatible VMs).
|
||||
// TypeError: (168-188): Unsupported call option "salt" (requires Constantinople-compatible VMs).
|
||||
@@ -0,0 +1,27 @@
|
||||
contract D {}
|
||||
contract C {
|
||||
function foo() pure internal {
|
||||
new D{salt:"abc", value:3, gas: 4};
|
||||
new D{slt:5, value:3};
|
||||
new D{val:5};
|
||||
new D{salt:"xyz", salt:"aaf"};
|
||||
new D{value:3, value:4};
|
||||
new D{random:5+5};
|
||||
new D{what:2130+5};
|
||||
new D{gas: 2};
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// TypeError: (64-98): Cannot set option "value" on a non-payable function type.
|
||||
// TypeError: (64-98): Function call option "gas" cannot be used with "new".
|
||||
// TypeError: (102-123): Unknown call option "slt". Valid options are "salt", "value" and "gas".
|
||||
// TypeError: (102-123): Cannot set option "value" on a non-payable function type.
|
||||
// TypeError: (127-139): Unknown call option "val". Valid options are "salt", "value" and "gas".
|
||||
// TypeError: (143-172): Duplicate option "salt".
|
||||
// TypeError: (176-199): Cannot set option "value" on a non-payable function type.
|
||||
// TypeError: (176-199): Cannot set option "value" on a non-payable function type.
|
||||
// TypeError: (203-220): Unknown call option "random". Valid options are "salt", "value" and "gas".
|
||||
// TypeError: (224-242): Unknown call option "what". Valid options are "salt", "value" and "gas".
|
||||
// TypeError: (246-259): Function call option "gas" cannot be used with "new".
|
||||
@@ -0,0 +1,14 @@
|
||||
contract C {
|
||||
struct gas { uint a; }
|
||||
function f() public returns (uint, uint) {
|
||||
try this.f() {
|
||||
gas memory x;
|
||||
} catch Error(string memory) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// Warning: (122-134): Unused local variable.
|
||||
Reference in New Issue
Block a user