Merge pull request #10163 from filecoin-project/mikers/create2test2
tests: itests: test create2 and destroy
This commit is contained in:
commit
4f5fea848c
1
itests/contracts/Create2Factory.hex
Normal file
1
itests/contracts/Create2Factory.hex
Normal file
File diff suppressed because one or more lines are too long
67
itests/contracts/Create2Factory.sol
Normal file
67
itests/contracts/Create2Factory.sol
Normal file
@ -0,0 +1,67 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.17;
|
||||
contract Create2Factory {
|
||||
|
||||
bytes32 savedSalt;
|
||||
|
||||
// Returns the address of the newly deployed contract
|
||||
function deploy(
|
||||
bytes32 _salt
|
||||
) public returns (address) {
|
||||
// This syntax is a newer way to invoke create2 without assembly, you just need to pass salt
|
||||
// https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
|
||||
savedSalt = _salt;
|
||||
(bool success, address ret) = deployDelegateCall(_salt);
|
||||
require(success);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function deployDelegateCall(
|
||||
bytes32 _salt
|
||||
) public returns (bool, address) {
|
||||
bytes memory data = abi.encodeWithSignature("_deploy(bytes32)", _salt);
|
||||
(bool success, bytes memory returnedData) = address(this).delegatecall(data);
|
||||
if(success){
|
||||
(address ret) = abi.decode(returnedData, (address));
|
||||
return (success, ret);
|
||||
}else{
|
||||
return (success, address(0));
|
||||
}
|
||||
}
|
||||
|
||||
function _deploy(bytes32 _salt) public returns (address) {
|
||||
// https://solidity-by-example.org/app/create1/
|
||||
// This syntax is a newer way to invoke create2 without assembly, you just need to pass salt
|
||||
// https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
|
||||
return address(new SelfDestruct{salt: _salt}(_salt));
|
||||
}
|
||||
|
||||
function test(address _address) public returns (address){
|
||||
|
||||
// run destroy() on _address
|
||||
SelfDestruct selfDestruct = SelfDestruct(_address);
|
||||
selfDestruct.destroy();
|
||||
|
||||
//verify data can still be accessed
|
||||
address ret = selfDestruct.sender();
|
||||
|
||||
// attempt and fail to deploy contract using salt
|
||||
(bool success, ) = deployDelegateCall(selfDestruct.salt());
|
||||
require(!success);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
contract SelfDestruct {
|
||||
address public sender;
|
||||
bytes32 public salt;
|
||||
constructor(bytes32 _salt) {
|
||||
sender = tx.origin;
|
||||
salt=_salt;
|
||||
}
|
||||
function destroy() public {
|
||||
selfdestruct(payable(msg.sender));
|
||||
}
|
||||
}
|
||||
|
2
itests/contracts/compile.sh
Executable file → Normal file
2
itests/contracts/compile.sh
Executable file → Normal file
@ -12,7 +12,7 @@ find . -name \*.sol -print0 |
|
||||
|
||||
#for these contracts we have 2 contracts in the same solidity file
|
||||
#this command grabs the correct bytecode for us
|
||||
for filename in Constructor TestApp ValueSender DeployValueTest; do
|
||||
for filename in Constructor TestApp ValueSender Create2Factory DeployValueTest; do
|
||||
echo $filename
|
||||
solc --bin $filename.sol | tail -n5|head -n1 | tr -d "\n" > $filename.hex
|
||||
done
|
||||
|
@ -3,6 +3,7 @@ package itests
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
@ -730,3 +731,58 @@ func TestFEVMDeployWithValue(t *testing.T) {
|
||||
//require balance of NewContract is testValue
|
||||
require.Equal(t, testValue.Uint64(), contractBalance)
|
||||
}
|
||||
|
||||
func TestFEVMDestroyCreate2(t *testing.T) {
|
||||
ctx, cancel, client := kit.SetupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
//deploy create2 factory contract
|
||||
filename := "contracts/Create2Factory.hex"
|
||||
fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename)
|
||||
|
||||
//construct salt for create2
|
||||
salt := make([]byte, 32)
|
||||
_, err := rand.Read(salt)
|
||||
require.NoError(t, err)
|
||||
|
||||
//deploy contract using create2 factory
|
||||
selfDestructAddress, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "deploy(bytes32)", salt)
|
||||
require.NoError(t, err)
|
||||
|
||||
//convert to filecoin actor address so we can call InvokeContractByFuncName
|
||||
ea, err := ethtypes.CastEthAddress(selfDestructAddress[12:])
|
||||
require.NoError(t, err)
|
||||
selfDestructAddressActor, err := ea.ToFilecoinAddress()
|
||||
require.NoError(t, err)
|
||||
|
||||
//read sender property from contract
|
||||
ret, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, selfDestructAddressActor, "sender()", []byte{})
|
||||
require.NoError(t, err)
|
||||
|
||||
//assert contract has correct data
|
||||
ethFromAddr := inputDataFromFrom(ctx, t, client, fromAddr)
|
||||
require.Equal(t, ethFromAddr, ret)
|
||||
|
||||
//run test() which 1.calls sefldestruct 2. verifies sender() is the correct value 3. attempts and fails to deploy via create2
|
||||
testSenderAddress, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "test(address)", selfDestructAddress)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testSenderAddress, ethFromAddr)
|
||||
|
||||
//read sender() but get response of 0x0 because of self destruct
|
||||
senderAfterDestroy, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, selfDestructAddressActor, "sender()", []byte{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte{}, senderAfterDestroy)
|
||||
|
||||
// deploy new contract at same address usign same salt
|
||||
newAddressSelfDestruct, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "deploy(bytes32)", salt)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, newAddressSelfDestruct, selfDestructAddress)
|
||||
|
||||
//verify sender() property is correct
|
||||
senderSecondCall, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, selfDestructAddressActor, "sender()", []byte{})
|
||||
require.NoError(t, err)
|
||||
|
||||
//assert contract has correct data
|
||||
require.Equal(t, ethFromAddr, senderSecondCall)
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user