@@ -3,9 +3,11 @@ package evm_storage_test
33import (
44 "encoding/hex"
55 "fmt"
6+ "math/big"
67 "strings"
78 "testing"
89
10+ "github.com/ethereum/go-ethereum/common"
911 "github.com/stretchr/testify/require"
1012
1113 "github.com/smartcontractkit/chainlink-testing-framework/framework/evm_storage"
@@ -14,7 +16,7 @@ import (
1416
1517// TestLayoutAPI that's the example of using helpers to override storage in your contracts
1618func TestLayoutAPI (t * testing.T ) {
17- t .Skip ("this test is for manual debugging and figuring out layout of custom structs" )
19+ // t.Skip("this test is for manual debugging and figuring out layout of custom structs")
1820 // load contract layout file, see testdata/layout.json
1921 // more docs here - https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#
2022 layout , err := evm_storage .New (layoutFile )
@@ -41,12 +43,92 @@ func TestLayoutAPI(t *testing.T) {
4143 return "0x" + hex .EncodeToString (buf )
4244 }
4345
44- slot := layout .ArraySlot ("a_signers" , 1 )
45- data := encodeFunc ("0x00000000000000000000000000000000000000a5" , 255 , 42 )
46- fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
47- r := rpc .New (testRPCURL , nil )
48- err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
49- require .NoError (t , err )
50- // verify it manually
51- // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "getASigner(uint256)(address,uint8,uint8)" --rpc-url http://localhost:8545 1
46+ {
47+ slot := layout .MustSlot ("number_uint256" )
48+ data := evm_storage .MustEncodeStorageSlot ("uint256" , big .NewInt (222 ))
49+ fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
50+ r := rpc .New (testRPCURL , nil )
51+ err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
52+ require .NoError (t , err )
53+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "number_uint256()(uint256)" --rpc-url http://localhost:8545
54+ }
55+ {
56+ slot := layout .MustSlot ("number_uint8" )
57+ data := evm_storage .MustEncodeStorageSlot ("uint8" , uint8 (8 ))
58+ fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
59+ r := rpc .New (testRPCURL , nil )
60+ err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
61+ require .NoError (t , err )
62+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "number_uint8()(uint8)" --rpc-url http://localhost:8545
63+ }
64+ {
65+ slot := layout .MustSlot ("number_int256" )
66+ data := evm_storage .MustEncodeStorageSlot ("uint256" , big .NewInt (221 ))
67+ fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
68+ r := rpc .New (testRPCURL , nil )
69+ err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
70+ require .NoError (t , err )
71+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "number_int256()(int256)" --rpc-url http://localhost:8545
72+ }
73+ {
74+ slot := layout .MustSlot ("_owner" )
75+ data := evm_storage .MustEncodeStorageSlot ("address" , common .HexToAddress ("0x5FbDB2315678afecb367f032d93F642f64180aa3" ))
76+ fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
77+ r := rpc .New (testRPCURL , nil )
78+ err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
79+ require .NoError (t , err )
80+ // private fields like _owner can only be verified by getter
81+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "getOwner()(address)" --rpc-url http://localhost:8545
82+ }
83+ {
84+ slot := layout .MustArraySlot ("a_signers" , 1 )
85+ data := encodeFunc ("0x00000000000000000000000000000000000000a5" , 255 , 42 )
86+ fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
87+ r := rpc .New (testRPCURL , nil )
88+ err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
89+ require .NoError (t , err )
90+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "getASigner(uint256)(address,uint8,uint8)" --rpc-url http://localhost:8545 1
91+ }
92+ {
93+ slot := layout .MustMapSlot ("s_signers" , "0x00000000000000000000000000000000000000a5" )
94+ data := encodeFunc ("0x00000000000000000000000000000000000000a5" , 254 , 40 )
95+ fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
96+ r := rpc .New (testRPCURL , nil )
97+ err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
98+ require .NoError (t , err )
99+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "getSSigner(address)(address,uint8,uint8)" 0x00000000000000000000000000000000000000a5 --rpc-url http://localhost:8545 1
100+ }
101+ {
102+ // offset example
103+ slot := layout .MustSlot ("boolean" )
104+ data := evm_storage .MustEncodeStorageSlot ("bool" , true )
105+ boolValue := evm_storage .ShiftHexByOffset (data , 1 )
106+ uint8Value := evm_storage .MustEncodeStorageSlot ("uint8" , uint8 (8 ))
107+ data = evm_storage .MergeHex (uint8Value , boolValue )
108+ fmt .Printf ("setting slot: %s with data: %s\n " , slot , data )
109+ r := rpc .New (testRPCURL , nil )
110+ err = r .AnvilSetStorageAt ([]interface {}{contractAddr , slot , data })
111+ require .NoError (t , err )
112+ // Contract code:
113+ // contract Counter {
114+ // address private _owner;
115+ // uint256 public number_uint256;
116+ // int256 public number_int256;
117+ // uint8 public number_uint8; <-- we need to change this
118+ // bool public boolean; <-- and this
119+ //
120+ // Example layout:
121+ // ╭----------------+-------------------------------------------+------+--------+-------+-------------------------╮
122+ // | Name | Type | Slot | Offset | Bytes | Contract |
123+ // |----------------+-------------------------------------------+------+--------+-------+-------------------------|
124+ // | number_uint8 | uint8 | 3 | 0 | 1 | src/Counter.sol:Counter |
125+ // |----------------+-------------------------------------------+------+--------+-------+-------------------------|
126+ // | boolean | bool | 3 | 1 | 1 | src/Counter.sol:Counter |
127+ // |----------------+-------------------------------------------+------+--------+-------+-------------------------|
128+ // Resulting value with offsets: 0x0000000000000000000000000000000000000000000000000000000000000108
129+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "boolean()(bool)" --rpc-url http://localhost:8545
130+ // true
131+ // cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "number_uint8()(uint8)" --rpc-url http://localhost:8545
132+ // 8
133+ }
52134}
0 commit comments