-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathStorage_ASM.sol
67 lines (50 loc) · 2.04 KB
/
Storage_ASM.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//SPDX-licence: MIT
pragma solidity "0.8.7";
/// @dev interface to the Storage fallback ASM contract (to get the returned values) + test env in Remix
contract Caller {
address callee;
constructor() {
callee = address(new Storage_ASM());
}
/// @dev static call to emulate call to a view function (fallback cannot be view)
function call_view() external view returns(uint256 ret) {
(bool success, bytes memory data) = callee.staticcall(new bytes(0)); //bypass the "this function might change state" error
require(success, "not success");
assembly {
ret := mload(add(data, 0x20)) //bytes to uint
}
}
function call_set(uint256 _val) external {
(bool success, ) = callee.call(abi.encode(_val)); //no function selector
require(success, "not success");
}
}
/// @dev the store & retrieve classic example, in assembly, using fallback as unique point of entry
contract Storage_ASM{
uint256 number=42069; //0xA455
/// @dev calldata size
fallback(bytes calldata args) external returns(bytes memory returned) { //only fallback def with return accepted in solc
assembly {
//retrieve() if calldata is empty:
if iszero(calldatasize()) {
// ret = new bytes(32)
returned := mload(0x40)
// new "memory end"
mstore(0x40, add(returned, 64))
// store bytes length (uint only->32)
mstore(returned, 32)
// value = number
let value := sload(number.slot)
// store it as only elt in the bytes returned
mstore(add(returned, 32), value)
}
//store(new_val) is calldataz non-empty:
if gt(calldatasize(), 0) {
//new_val is the only data worth in calldata
let new_val := calldataload(0)
// number = new_val, will cast as uint256
sstore(number.slot, new_val)
}
}
}
}