Merge pull request #10010 from filecoin-project/snissn/delegatecalltest3
fevm_test: delegate call test
This commit is contained in:
commit
2f03bf9372
1
itests/contracts/DelegatecallActor.hex
Normal file
1
itests/contracts/DelegatecallActor.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b5061018c806100206000396000f3fe6080604052600436106100345760003560e01c806361bc221a146100395780636466414b146100645780638ada066e14610080575b600080fd5b34801561004557600080fd5b5061004e6100ab565b60405161005b91906100dd565b60405180910390f35b61007e60048036038101906100799190610129565b6100b1565b005b34801561008c57600080fd5b506100956100bb565b6040516100a291906100dd565b60405180910390f35b60005481565b8060008190555050565b60008054905090565b6000819050919050565b6100d7816100c4565b82525050565b60006020820190506100f260008301846100ce565b92915050565b600080fd5b610106816100c4565b811461011157600080fd5b50565b600081359050610123816100fd565b92915050565b60006020828403121561013f5761013e6100f8565b5b600061014d84828501610114565b9150509291505056fea2646970667358221220cf4567855a30be48cde5cdbff495bdaa4052e2c4540678b97284af53a4e5dbd164736f6c63430008110033
|
13
itests/contracts/DelegatecallActor.sol
Normal file
13
itests/contracts/DelegatecallActor.sol
Normal file
@ -0,0 +1,13 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
contract DelegatecallActor {
|
||||
uint public counter;
|
||||
|
||||
function getCounter() public view returns (uint){
|
||||
return counter;
|
||||
}
|
||||
function setVars(uint _counter) public payable {
|
||||
counter = _counter;
|
||||
}
|
||||
}
|
1
itests/contracts/DelegatecallStorage.hex
Normal file
1
itests/contracts/DelegatecallStorage.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b50610477806100206000396000f3fe6080604052600436106100345760003560e01c806361bc221a146100395780638ada066e14610064578063d1e0f3081461008f575b600080fd5b34801561004557600080fd5b5061004e6100bf565b60405161005b919061022c565b60405180910390f35b34801561007057600080fd5b506100796100c5565b604051610086919061022c565b60405180910390f35b6100a960048036038101906100a491906102d6565b6100ce565b6040516100b6919061022c565b60405180910390f35b60005481565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516024016100f9919061022c565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101839190610387565b600060405180830381855af49150503d80600081146101be576040519150601f19603f3d011682016040523d82523d6000602084013e6101c3565b606091505b5050905080610207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101fe90610421565b60405180910390fd5b60005491505092915050565b6000819050919050565b61022681610213565b82525050565b6000602082019050610241600083018461021d565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102778261024c565b9050919050565b6102878161026c565b811461029257600080fd5b50565b6000813590506102a48161027e565b92915050565b6102b381610213565b81146102be57600080fd5b50565b6000813590506102d0816102aa565b92915050565b600080604083850312156102ed576102ec610247565b5b60006102fb85828601610295565b925050602061030c858286016102c1565b9150509250929050565b600081519050919050565b600081905092915050565b60005b8381101561034a57808201518184015260208101905061032f565b60008484015250505050565b600061036182610316565b61036b8185610321565b935061037b81856020860161032c565b80840191505092915050565b60006103938284610356565b915081905092915050565b600082825260208201905092915050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b600061040b60228361039e565b9150610416826103af565b604082019050919050565b6000602082019050818103600083015261043a816103fe565b905091905056fea26469706673582212203663909b8221e9b87047be99420c00339af1430c085260df209b909ed8e0f05164736f6c63430008110033
|
17
itests/contracts/DelegatecallStorage.sol
Normal file
17
itests/contracts/DelegatecallStorage.sol
Normal file
@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
contract DelegatecallStorage {
|
||||
uint public counter;
|
||||
|
||||
function getCounter() public view returns (uint){
|
||||
return counter;
|
||||
}
|
||||
function setVars(address _contract, uint _counter) public payable returns (uint){
|
||||
(bool success, ) = _contract.delegatecall(
|
||||
abi.encodeWithSignature("setVars(uint256)", _counter)
|
||||
);
|
||||
require(success, 'Error message: Delegatecall failed');
|
||||
return counter;
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061051c806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610193919061047e565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104b2565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b925082820261046081610337565b915082820484148315176104775761047661040d565b5b5092915050565b600061048982610337565b915061049483610337565b92508282039050818111156104ac576104ab61040d565b5b92915050565b60006104bd82610337565b91506104c883610337565b92508282019050808211156104e0576104df61040d565b5b9291505056fea26469706673582212205ede41ff9072784ccc19ac18de0781558d305a8139361fa85dc51a8614e47d8c64736f6c63430008110033
|
||||
608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061051c806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610193919061047e565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104b2565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b925082820261046081610337565b915082820484148315176104775761047661040d565b5b5092915050565b600061048982610337565b915061049483610337565b92508282039050818111156104ac576104ab61040d565b5b92915050565b60006104bd82610337565b91506104c883610337565b92508282019050808211156104e0576104df61040d565b5b9291505056fea2646970667358221220050cdcfbe2911d041d2e6c355dbb6a0ca8ca70b500865bf33d9a2e5f4ac5a4e164736f6c63430008110033
|
6
itests/contracts/compile.sh
Executable file
6
itests/contracts/compile.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#use the solc compiler https://docs.soliditylang.org/en/v0.8.17/installing-solidity.html
|
||||
# to compile all of the .sol files to their corresponding evm binary files stored as .hex
|
||||
# solc outputs to stdout a format that we just want to grab the last line of and then remove the trailing newline on that line
|
||||
|
||||
find -type f -name \*.sol -print0 |
|
||||
xargs -0 -I{} bash -c 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)'
|
@ -1,67 +1,64 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
// TestFEVMBasic does a basic fevm contract installation and invocation
|
||||
func TestFEVMBasic(t *testing.T) {
|
||||
// TODO the contract installation and invocation can be lifted into utility methods
|
||||
// He who writes the second test, shall do that.
|
||||
kit.QuietMiningLogs()
|
||||
// convert a simple byte array into input data which is a left padded 32 byte array
|
||||
func inputDataFromArray(input []byte) []byte {
|
||||
inputData := make([]byte, 32)
|
||||
copy(inputData[32-len(input):], input[:])
|
||||
return inputData
|
||||
}
|
||||
|
||||
// convert a "from" address into input data which is a left padded 32 byte array
|
||||
func inputDataFromFrom(ctx context.Context, t *testing.T, client *kit.TestFullNode, from address.Address) []byte {
|
||||
fromId, err := client.StateLookupID(ctx, from, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
senderEthAddr, err := ethtypes.EthAddressFromFilecoinAddress(fromId)
|
||||
require.NoError(t, err)
|
||||
inputData := make([]byte, 32)
|
||||
copy(inputData[32-len(senderEthAddr):], senderEthAddr[:])
|
||||
return inputData
|
||||
}
|
||||
|
||||
func setupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *kit.TestFullNode) {
|
||||
kit.QuietMiningLogs()
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
return ctx, cancel, client
|
||||
}
|
||||
|
||||
// TestFEVMBasic does a basic fevm contract installation and invocation
|
||||
func TestFEVMBasic(t *testing.T) {
|
||||
|
||||
ctx, cancel, client := setupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
filename := "contracts/SimpleCoin.hex"
|
||||
// install contract
|
||||
contractHex, err := os.ReadFile("contracts/SimpleCoin.hex")
|
||||
require.NoError(t, err)
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
|
||||
fromAddr, err := client.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
result := client.EVM().DeployContract(ctx, fromAddr, contract)
|
||||
|
||||
idAddr, err := address.NewIDAddress(result.ActorID)
|
||||
require.NoError(t, err)
|
||||
t.Logf("actor ID address is %s", idAddr)
|
||||
fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename)
|
||||
|
||||
// invoke the contract with owner
|
||||
{
|
||||
entryPoint, err := hex.DecodeString("f8b2cb4f")
|
||||
require.NoError(t, err)
|
||||
|
||||
inputData, err := hex.DecodeString("000000000000000000000000ff00000000000000000000000000000000000064")
|
||||
require.NoError(t, err)
|
||||
|
||||
wait := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData)
|
||||
|
||||
require.True(t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed")
|
||||
|
||||
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
|
||||
require.NoError(t, err)
|
||||
inputData := inputDataFromFrom(ctx, t, client, fromAddr)
|
||||
result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData)
|
||||
|
||||
expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000002710")
|
||||
require.NoError(t, err)
|
||||
@ -70,34 +67,19 @@ func TestFEVMBasic(t *testing.T) {
|
||||
|
||||
// invoke the contract with non owner
|
||||
{
|
||||
entryPoint, err := hex.DecodeString("f8b2cb4f")
|
||||
require.NoError(t, err)
|
||||
|
||||
inputData, err := hex.DecodeString("000000000000000000000000ff00000000000000000000000000000000000065")
|
||||
require.NoError(t, err)
|
||||
|
||||
wait := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData)
|
||||
require.True(t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed")
|
||||
|
||||
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
|
||||
require.NoError(t, err)
|
||||
inputData := inputDataFromFrom(ctx, t, client, fromAddr)
|
||||
inputData[31]++ // change the pub address to one that has 0 balance by incrementing the last byte of the address
|
||||
result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData)
|
||||
|
||||
expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, expectedResult)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TestFEVMETH0 tests that the ETH0 actor is in genesis
|
||||
func TestFEVMETH0(t *testing.T) {
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
ctx, cancel, client := setupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
eth0id, err := address.NewIDAddress(1001)
|
||||
@ -112,3 +94,41 @@ func TestFEVMETH0(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, *act.Address, eth0Addr)
|
||||
}
|
||||
|
||||
// TestFEVMDelegateCall deploys two contracts and makes a delegate call transaction
|
||||
func TestFEVMDelegateCall(t *testing.T) {
|
||||
|
||||
ctx, cancel, client := setupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
//install contract Actor
|
||||
filenameActor := "contracts/DelegatecallActor.hex"
|
||||
fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)
|
||||
//install contract Storage
|
||||
filenameStorage := "contracts/DelegatecallStorage.hex"
|
||||
fromAddrStorage, storageAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage)
|
||||
require.Equal(t, fromAddr, fromAddrStorage)
|
||||
|
||||
//call Contract Storage which makes a delegatecall to contract Actor
|
||||
//this contract call sets the "counter" variable to 7, from default value 0
|
||||
|
||||
inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr)
|
||||
inputDataValue := inputDataFromArray([]byte{7})
|
||||
inputData := append(inputDataContract, inputDataValue...)
|
||||
|
||||
//verify that the returned value of the call to setvars is 7
|
||||
result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVars(address,uint256)", inputData)
|
||||
expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, expectedResult)
|
||||
|
||||
//test the value is 7 via calling the getter
|
||||
result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{})
|
||||
require.Equal(t, result, expectedResult)
|
||||
|
||||
//test the value is 0 via calling the getter on the Actor contract
|
||||
result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{})
|
||||
expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, expectedResultActor)
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-varint"
|
||||
@ -77,6 +79,23 @@ func (e *EVM) DeployContract(ctx context.Context, sender address.Address, byteco
|
||||
return result
|
||||
}
|
||||
|
||||
func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string) (address.Address, address.Address) {
|
||||
contractHex, err := os.ReadFile(binFilename)
|
||||
require.NoError(e.t, err)
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(e.t, err)
|
||||
|
||||
fromAddr, err := e.WalletDefaultAddress(ctx)
|
||||
require.NoError(e.t, err)
|
||||
|
||||
result := e.DeployContract(ctx, fromAddr, contract)
|
||||
|
||||
idAddr, err := address.NewIDAddress(result.ActorID)
|
||||
require.NoError(e.t, err)
|
||||
return fromAddr, idAddr
|
||||
}
|
||||
|
||||
func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target address.Address, selector []byte, inputData []byte) *api.MsgLookup {
|
||||
require := require.New(e.t)
|
||||
|
||||
@ -212,6 +231,23 @@ func (e *EVM) ComputeContractAddress(deployer ethtypes.EthAddress, nonce uint64)
|
||||
return *(*ethtypes.EthAddress)(hasher.Sum(nil)[12:])
|
||||
}
|
||||
|
||||
func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) []byte {
|
||||
entryPoint := CalcFuncSignature(funcSignature)
|
||||
wait := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData)
|
||||
require.True(e.t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed")
|
||||
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
|
||||
require.NoError(e.t, err)
|
||||
return result
|
||||
}
|
||||
|
||||
// function signatures are the first 4 bytes of the hash of the function name and types
|
||||
func CalcFuncSignature(funcName string) []byte {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write([]byte(funcName))
|
||||
hash := hasher.Sum(nil)
|
||||
return hash[:4]
|
||||
}
|
||||
|
||||
// TODO: cleanup and put somewhere reusable.
|
||||
type apiIpldStore struct {
|
||||
ctx context.Context
|
||||
|
Loading…
Reference in New Issue
Block a user