Skip to content
This repository was archived by the owner on Aug 20, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 52 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ To assemble `src/main.etk` you will need to invoke `eas`:

```console
$ eas src/main.etk
3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500
3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762016da0810690815414603c575f5ffd5b62016da001545f5260205ff35b5f5ffd5b62016da042064281555f359062016da0015500
```

It's also possible to remove the `etk` preproccessing by doing a roundtrip --
Expand All @@ -31,7 +31,7 @@ $ disease --code 0x$(eas src/main.etk)
0: caller
1: push20 0xfffffffffffffffffffffffffffffffffffffffe
16: eq
17: push1 0x44
17: push1 0x4d
19: jumpi

1a: push1 0x20
Expand All @@ -45,46 +45,57 @@ $ disease --code 0x$(eas src/main.etk)
23: revert

24: jumpdest
25: push3 0x018000
29: push0
2a: calldataload
2b: mod
2c: dup1
2d: sload
2e: push0
2f: calldataload
30: eq
31: push1 0x37
33: jumpi

34: push0
35: push0
36: revert

37: jumpdest
38: push3 0x018000
3c: add
3d: sload
3e: push0
3f: mstore
40: push1 0x20
42: push0
43: return

44: jumpdest
45: push3 0x018000
49: timestamp
4a: mod
4b: timestamp
4c: dup2
4d: sstore
4e: push0
4f: calldataload
50: swap1
51: push3 0x018000
55: add
25: push0
26: calldataload
27: dup1
28: iszero
29: push1 0x49
2b: jumpi

2c: push3 0x016da0
30: dup2
31: mod
32: swap1
33: dup2
34: sload
35: eq
36: push1 0x3c
38: jumpi

39: push0
3a: push0
3b: revert

3c: jumpdest
3d: push3 0x016da0
41: add
42: sload
43: push0
44: mstore
45: push1 0x20
47: push0
48: return

49: jumpdest
4a: push0
4b: push0
4c: revert

4d: jumpdest
4e: push3 0x016da0
52: timestamp
53: mod
54: timestamp
55: dup2
56: sstore
57: stop
57: push0
58: calldataload
59: swap1
5a: push3 0x016da0
5e: add
5f: sstore
60: stop

```

### Control-flow Graph
Expand Down
Binary file modified docs/cfg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 30 additions & 22 deletions src/main.etk
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,16 @@

# buflen returns the HISTORY_BUFFER_LENGTH as defined in the EIP.
%def buflen()
98304
93600
%end

# sysaddr is the address which calls the contract to submit a new root.
%def sysaddr()
0xfffffffffffffffffffffffffffffffffffffffe
%end

# get_input loads the first word of input from calldata.
%macro get_input()
push0 # [0]
calldataload # [calldata[0..32]]
%end

# revert sets up and then executes a revert instruction.
%macro revert()
# do_revert sets up and then executes a revert(0,0) operation.
%macro do_revert()
push0 # [0]
push0 # [0, 0]
revert # []
Expand Down Expand Up @@ -74,31 +68,40 @@ start:
# Jump to continue if length-check passed, otherwise revert.
push1 loadtime # [loadtime_lbl, calldatasize == 32]
jumpi # []
%revert() # []

%do_revert() # []

loadtime:
jumpdest

# Load input timestamp.
push0 # [0]
calldataload # [input_timestamp]
dup1 # [input_timestamp, input_timestamp]

# Verify input timestamp is non-zero.
iszero # [input_timestamp == 0, input_timestamp]
push1 throw # [throw_lbl, input_timestamp == 0, input_timestamp]
jumpi # [input_timestamp]

# Compute the timestamp index and load from storage.
jumpdest # []
push3 buflen() # [buflen]
%get_input() # [time, buflen]
mod # [time_index]
dup1 # [time_index, time_index]
sload # [timestamp, time_index]
push3 buflen() # [buflen, input_timestamp]
dup2 # [input_timestamp, buflen, input_timestamp]
mod # [time_index, input_timestamp]
swap1 # [input_timestamp, time_index]
dup2 # [time_index, input_timestamp, time_index]
sload # [stored_timestamp, input_timestamp, time_index]

# Verify stored timestamp matches input timestamp. It's possible these
# don't match if the slot has been overwritten by the ring buffer or if
# the timestamp input wasn't a valid previous timestamp.
%get_input() # [input, timestamp, time_index]
eq # [input == timestamp, time_index]
eq # [stored_timestamp == input_timestamp, time_index]
push1 loadroot # [loadroot_lbl, input == timestamp, time_index]
jumpi # [time_index]
%revert() # []

%do_revert() # []

loadroot:
# Extend index to get root index.
jumpdest
jumpdest # [time_index]
push3 buflen() # [buflen, time_index]
add # [root_index]
sload # [root]
Expand All @@ -112,6 +115,11 @@ loadroot:
push0 # [offset, size]
return # []

throw:
# Reverts current execution with no return data.
jumpdest
%do_revert()

submit:
jumpdest # []

Expand Down
11 changes: 8 additions & 3 deletions test/Contract.t.sol.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "../src/Contract.sol";

address constant addr = 0x000000000000000000000000000000000000000b;
address constant sysaddr = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE;
uint256 constant buflen = 98304;
uint256 constant buflen = 93600;
bytes32 constant root = hex"88e96d4537bea4d9c05d12549907b32561d3bf31f45aae734cdc119f13406cb6";

function timestamp() view returns (bytes32) {
Expand Down Expand Up @@ -87,6 +87,11 @@ contract ContractTest is Test {
(ret, data) = unit.call(bytes.concat(bytes32(time+1)));
assertFalse(ret);
assertEq(data, hex"");

// Timestamp zero should fail.
(ret, data) = unit.call(bytes.concat(bytes32(0)));
assertFalse(ret);
assertEq(data, hex"");
}

// testUpdate verifies the set functionality of the contract.
Expand Down Expand Up @@ -137,7 +142,7 @@ contract ContractTest is Test {
uint256 start = block.timestamp;

// Saturate storage with fake roots.
for (uint256 i = 0; i < 8192; i += 1) {
for (uint256 i = 0; i < buflen / 12; i += 1) {
bytes32 pbbr = bytes32(i*1337);
vm.prank(sysaddr);
(bool ret, bytes memory data) = unit.call(bytes.concat(pbbr));
Expand All @@ -147,7 +152,7 @@ contract ContractTest is Test {
}

// Attempt to read all values in same block context.
for (uint256 i = 0; i < 8192; i += 1) {
for (uint256 i = 0; i < buflen / 12; i += 1) {
bytes32 time = bytes32(uint256(start+i*12));
(bool ret, bytes memory got) = unit.call(bytes.concat(time));
assertTrue(ret);
Expand Down