|
| 1 | +pragma solidity ^0.8.25; |
| 2 | + |
| 3 | +import {Animal} from "./Animal.sol"; |
| 4 | +import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; |
| 5 | + |
| 6 | +contract ZOO is Pausable { |
| 7 | + uint256 public isSolved; |
| 8 | + AnimalWrapper[] public animals; |
| 9 | + |
| 10 | + struct AnimalWrapper { |
| 11 | + Animal animal; |
| 12 | + uint256 counter; |
| 13 | + } |
| 14 | + |
| 15 | + uint256 constant ADD = 0x10; |
| 16 | + uint256 constant EDIT = 0x20; |
| 17 | + uint256 constant DEL = 0x30; |
| 18 | + |
| 19 | + uint256 constant EDIT_NAME = 0x21; |
| 20 | + uint256 constant EDIT_TYPE = 0x22; |
| 21 | + |
| 22 | + uint256 constant TRACK_MAX = 0x100; |
| 23 | + |
| 24 | + constructor() { |
| 25 | + animals.push(AnimalWrapper(new Animal("PANDA", "PND"), 0)); |
| 26 | + animals.push(AnimalWrapper(new Animal("TIGER", "TGR"), 0)); |
| 27 | + animals.push(AnimalWrapper(new Animal("HORSE", "HRS"), 0)); |
| 28 | + animals.push(AnimalWrapper(new Animal("ZIBRA", "ZBR"), 0)); |
| 29 | + animals.push(AnimalWrapper(new Animal("HIPPO", "HPO"), 0)); |
| 30 | + animals.push(AnimalWrapper(new Animal("LION", "LON"), 0)); |
| 31 | + animals.push(AnimalWrapper(new Animal("BEAR", "BAR"), 0)); |
| 32 | + animals.push(AnimalWrapper(new Animal("WOLF", "WLF"), 0)); |
| 33 | + animals.push(AnimalWrapper(new Animal("ELEPHANT", "ELP"), 0)); |
| 34 | + animals.push(AnimalWrapper(new Animal("RHINO", "RNO"), 0)); |
| 35 | + |
| 36 | + // The ZOO is not opened yet :( |
| 37 | + _pause(); |
| 38 | + } |
| 39 | + |
| 40 | + function commit(bytes memory data) internal whenNotPaused { |
| 41 | + assembly { |
| 42 | + let counter := 0 |
| 43 | + let length := mload(data) |
| 44 | + |
| 45 | + for { let i := 0 } lt(i, length) { i := add(i, 1) } { |
| 46 | + let idx |
| 47 | + let name |
| 48 | + |
| 49 | + let memPtr := mload(0x40) |
| 50 | + |
| 51 | + let ptr := mload(add(add(data, 0x20), counter)) |
| 52 | + idx := mload(ptr) |
| 53 | + name := add(ptr, 0x20) |
| 54 | + let name_length := mload(name) |
| 55 | + counter := add(counter, 0x20) |
| 56 | + |
| 57 | + mstore(0x00, animals.slot) |
| 58 | + let slot_hash := keccak256(0x00, 0x20) |
| 59 | + let animal_addr := sload(add(slot_hash, mul(2, idx))) |
| 60 | + let animal_counter := sload(add(add(slot_hash, mul(2, idx)), 1)) |
| 61 | + |
| 62 | + if gt(animal_counter, 50) { revert(0, 0) } |
| 63 | + |
| 64 | + mstore(memPtr, shl(0xe0, 0x1436163e)) |
| 65 | + mstore(add(memPtr, 0x4), caller()) |
| 66 | + |
| 67 | + pop(call(gas(), animal_addr, 0x00, memPtr, 0x24, memPtr, 0x00)) |
| 68 | + |
| 69 | + mstore(memPtr, shl(0xe0, 0x61bc221a)) |
| 70 | + pop(staticcall(gas(), animal_addr, memPtr, 0x20, memPtr, 0x20)) |
| 71 | + |
| 72 | + let animal_count := sub(mload(memPtr), 0x1) |
| 73 | + |
| 74 | + mstore(memPtr, shl(0xe0, 0xfe55932a)) |
| 75 | + mstore(add(memPtr, 0x4), animal_count) |
| 76 | + mstore(add(memPtr, 0x24), 0x40) |
| 77 | + mstore(add(memPtr, 0x44), name_length) |
| 78 | + mcopy(add(memPtr, 0x64), name, name_length) |
| 79 | + |
| 80 | + pop(call(gas(), animal_addr, 0x00, memPtr, 0x84, memPtr, 0x00)) |
| 81 | + |
| 82 | + sstore(add(add(slot_hash, mul(2, idx)), 1), add(animal_counter, 1)) |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + fallback() external payable { |
| 88 | + function(bytes memory)[] memory functions = new function( |
| 89 | + bytes memory |
| 90 | + )[](1); |
| 91 | + functions[0] = commit; |
| 92 | + |
| 93 | + bytes memory local_animals; |
| 94 | + assembly { |
| 95 | + let arr := mload(0x40) |
| 96 | + let size := calldatasize() |
| 97 | + mstore(arr, size) |
| 98 | + let size_align := add(add(size, sub(0x20, mod(size, 0x20))), 0x20) |
| 99 | + mstore(0x40, add(arr, size_align)) |
| 100 | + calldatacopy(add(arr, 0x20), 0, size) |
| 101 | + |
| 102 | + local_animals := mload(0x40) |
| 103 | + mstore(0x40, add(local_animals, 0x120)) |
| 104 | + |
| 105 | + for { let i := 0 } lt(i, size) {} { |
| 106 | + let op := mload(add(add(arr, 0x20), i)) |
| 107 | + op := shr(0xf8, op) |
| 108 | + i := add(i, 1) |
| 109 | + |
| 110 | + switch op |
| 111 | + case 0x10 { |
| 112 | + let idx := mload(add(add(arr, 0x20), i)) |
| 113 | + idx := shr(0xf8, idx) |
| 114 | + i := add(i, 1) |
| 115 | + |
| 116 | + if gt(idx, 7) { revert(0, 0) } |
| 117 | + |
| 118 | + let name_length := mload(add(add(arr, 0x20), i)) |
| 119 | + name_length := shr(0xf0, name_length) |
| 120 | + i := add(i, 2) |
| 121 | + |
| 122 | + let animal_index := mload(add(add(arr, 0x20), i)) |
| 123 | + animal_index := shr(0xf0, animal_index) |
| 124 | + i := add(i, 2) |
| 125 | + |
| 126 | + let temp := mload(0x40) |
| 127 | + mstore(temp, animal_index) |
| 128 | + mcopy(add(temp, 0x40), add(add(arr, 0x20), i), name_length) |
| 129 | + i := add(i, name_length) |
| 130 | + |
| 131 | + name_length := add(name_length, sub(0x20, mod(name_length, 0x20))) |
| 132 | + |
| 133 | + mstore(add(temp, 0x20), name_length) |
| 134 | + mstore(0x40, add(temp, add(name_length, 0x40))) |
| 135 | + |
| 136 | + mstore(add(add(local_animals, 0x20), mul(0x20, idx)), temp) |
| 137 | + |
| 138 | + let animals_count := mload(local_animals) |
| 139 | + mstore(local_animals, add(animals_count, 1)) |
| 140 | + } |
| 141 | + case 0x20 { |
| 142 | + let idx := mload(add(add(arr, 0x20), i)) |
| 143 | + idx := shr(0xf8, idx) |
| 144 | + i := add(i, 1) |
| 145 | + |
| 146 | + if gt(idx, 7) { revert(0, 0) } |
| 147 | + |
| 148 | + let offset := add(add(local_animals, 0x20), mul(0x20, idx)) |
| 149 | + let temp := mload(offset) |
| 150 | + |
| 151 | + let edit_type := mload(add(add(arr, 0x20), i)) |
| 152 | + edit_type := shr(0xf8, edit_type) |
| 153 | + i := add(i, 1) |
| 154 | + |
| 155 | + switch edit_type |
| 156 | + case 0x21 { |
| 157 | + let name_length := mload(add(add(arr, 0x20), i)) |
| 158 | + name_length := shr(0xf0, name_length) |
| 159 | + i := add(i, 2) |
| 160 | + |
| 161 | + mcopy(add(temp, 0x40), add(add(arr, 0x20), i), name_length) |
| 162 | + } |
| 163 | + case 0x22 { |
| 164 | + let new_type := mload(add(add(arr, 0x20), i)) |
| 165 | + new_type := shr(0xf0, new_type) |
| 166 | + i := add(i, 2) |
| 167 | + |
| 168 | + mstore(add(temp, 0x20), new_type) |
| 169 | + } |
| 170 | + } |
| 171 | + case 0x30 { |
| 172 | + let idx := mload(add(add(arr, 0x20), i)) |
| 173 | + idx := shr(0xf8, idx) |
| 174 | + i := add(i, 1) |
| 175 | + |
| 176 | + if gt(idx, 7) { revert(0, 0) } |
| 177 | + |
| 178 | + let offset := add(add(local_animals, 0x20), mul(0x20, idx)) |
| 179 | + let temp := mload(offset) |
| 180 | + |
| 181 | + let copy_size := sub(0x100, mul(0x20, idx)) |
| 182 | + mcopy(offset, add(offset, 0x20), copy_size) |
| 183 | + |
| 184 | + let animals_count := mload(local_animals) |
| 185 | + animals_count := sub(animals_count, 1) |
| 186 | + mstore(local_animals, animals_count) |
| 187 | + } |
| 188 | + default { break } |
| 189 | + } |
| 190 | + } |
| 191 | + functions[0](local_animals); |
| 192 | + } |
| 193 | + |
| 194 | + receive() external payable {} |
| 195 | +} |
0 commit comments