|
| 1 | +use ingot::evm |
| 2 | +use ingot::math |
| 3 | + |
| 4 | +unsafe fn avail() -> u256 { |
| 5 | + let ptr: u256 = evm::mload(offset: 64) |
| 6 | + |
| 7 | + if ptr == 0x00 { |
| 8 | + return 96 |
| 9 | + } else { |
| 10 | + return ptr |
| 11 | + } |
| 12 | +} |
| 13 | + |
| 14 | +unsafe fn alloc(len: u256) -> u256 { |
| 15 | + let ptr: u256 = avail() |
| 16 | + evm::mstore(offset: 64, value: ptr + len) |
| 17 | + return ptr |
| 18 | +} |
| 19 | + |
| 20 | +struct Cursor { |
| 21 | + cur: u256 |
| 22 | + len: u256 |
| 23 | + |
| 24 | + pub fn new(len: u256) -> Self { |
| 25 | + return Cursor(cur: 0, len) |
| 26 | + } |
| 27 | + |
| 28 | + /// Increment the value of `cur` by `len` and return the value of `cur` before being incremented. |
| 29 | + /// Reverts if the cursor is advanced beyond the given length. |
| 30 | + pub fn advance(mut self, len: u256) -> u256 { |
| 31 | + let cur: u256 = self.cur |
| 32 | + assert cur + len < self.len + 1 |
| 33 | + self.cur += len |
| 34 | + return cur |
| 35 | + } |
| 36 | + |
| 37 | + /// Length of the cursor remaining. |
| 38 | + pub fn remainder(self) -> u256 { |
| 39 | + return self.len - self.cur |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +/// EVM memory buffer abstraction. |
| 44 | +pub struct MemoryBuffer { |
| 45 | + offset: u256 |
| 46 | + len: u256 |
| 47 | + |
| 48 | + pub fn new(len: u256) -> Self { |
| 49 | + unsafe { |
| 50 | + return MemoryBuffer(offset: alloc(len: len + 30), len) |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + pub fn from_u8(value: u8) -> Self { |
| 55 | + let mut buf: MemoryBuffer = MemoryBuffer::new(len: 1) |
| 56 | + let mut writer: MemoryBufferWriter = buf.writer() |
| 57 | + writer.write(value) |
| 58 | + return buf |
| 59 | + } |
| 60 | + |
| 61 | + /// Length of the buffer in bytes. |
| 62 | + pub fn len(self) -> u256 { |
| 63 | + return self.len |
| 64 | + } |
| 65 | + |
| 66 | + /// The start of the buffer in EVM memory. |
| 67 | + pub fn offset(self) -> u256 { |
| 68 | + return self.offset |
| 69 | + } |
| 70 | + |
| 71 | + /// Returns a new buffer reader. |
| 72 | + pub fn reader(self) -> MemoryBufferReader { |
| 73 | + return MemoryBufferReader::new(buf: self) |
| 74 | + } |
| 75 | + |
| 76 | + /// Returns a new buffer writer. |
| 77 | + pub fn writer(mut self) -> MemoryBufferWriter { |
| 78 | + return MemoryBufferWriter::new(buf: self) |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +/// Memory buffer writer abstraction. |
| 83 | +pub struct MemoryBufferWriter { |
| 84 | + buf: MemoryBuffer |
| 85 | + cur: Cursor |
| 86 | + |
| 87 | + /// Returns a new writer for the given buffer. |
| 88 | + pub fn new(mut buf: MemoryBuffer) -> Self { |
| 89 | + return MemoryBufferWriter( |
| 90 | + buf, |
| 91 | + cur: Cursor::new(len: buf.len()) |
| 92 | + ) |
| 93 | + } |
| 94 | + |
| 95 | + /// The number of bytes remaining to be written. |
| 96 | + pub fn remainder(self) -> u256 { |
| 97 | + return self.cur.remainder() |
| 98 | + } |
| 99 | + |
| 100 | + pub fn write_offset(mut self, len: u256) -> u256 { |
| 101 | + return self.buf.offset() + self.cur.advance(len) |
| 102 | + } |
| 103 | + |
| 104 | + pub fn write_n(mut self, value: u256, len: u256) { |
| 105 | + let offset: u256 = self.write_offset(len) |
| 106 | + let shifted_value: u256 = evm::shl(bits: 256 - len * 8, value) |
| 107 | + unsafe { evm::mstore(offset, value: shifted_value) } |
| 108 | + } |
| 109 | + |
| 110 | + pub fn write_buf(mut self, buf: MemoryBuffer) { |
| 111 | + let mut reader: MemoryBufferReader = buf.reader() |
| 112 | + |
| 113 | + while true { |
| 114 | + let bytes_remaining: u256 = reader.remainder() |
| 115 | + |
| 116 | + if bytes_remaining >= 32 { |
| 117 | + self.write(value: reader.read_u256()) |
| 118 | + } else if bytes_remaining == 0 { |
| 119 | + break |
| 120 | + } else { |
| 121 | + self.write(value: reader.read_u8()) |
| 122 | + } |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + pub fn write<T: MemoryBufferWrite>(mut self, value: T) { |
| 127 | + value.write_buf(writer: self) |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +pub trait MemoryBufferWrite { |
| 132 | + fn write_buf(self, mut writer: MemoryBufferWriter); |
| 133 | +} |
| 134 | + |
| 135 | +impl MemoryBufferWrite for u256 { |
| 136 | + fn write_buf(self, mut writer: MemoryBufferWriter) { |
| 137 | + let offset: u256 = writer.write_offset(len: 32) |
| 138 | + unsafe { evm::mstore(offset, value: self) } |
| 139 | + } |
| 140 | +} |
| 141 | + |
| 142 | +impl MemoryBufferWrite for u128 { |
| 143 | + fn write_buf(self, mut writer: MemoryBufferWriter) { |
| 144 | + writer.write_n(value: u256(self), len: 16) |
| 145 | + } |
| 146 | +} |
| 147 | + |
| 148 | +impl MemoryBufferWrite for u64 { |
| 149 | + fn write_buf(self, mut writer: MemoryBufferWriter) { |
| 150 | + writer.write_n(value: u256(self), len: 8) |
| 151 | + } |
| 152 | +} |
| 153 | + |
| 154 | +impl MemoryBufferWrite for u32 { |
| 155 | + fn write_buf(self, mut writer: MemoryBufferWriter) { |
| 156 | + writer.write_n(value: u256(self), len: 4) |
| 157 | + } |
| 158 | +} |
| 159 | + |
| 160 | +impl MemoryBufferWrite for u16 { |
| 161 | + fn write_buf(self, mut writer: MemoryBufferWriter) { |
| 162 | + writer.write_n(value: u256(self), len: 2) |
| 163 | + } |
| 164 | +} |
| 165 | + |
| 166 | +impl MemoryBufferWrite for u8 { |
| 167 | + fn write_buf(self, mut writer: MemoryBufferWriter) { |
| 168 | + let offset: u256 = writer.write_offset(len: 1) |
| 169 | + unsafe { evm::mstore8(offset, value: self) } |
| 170 | + } |
| 171 | +} |
| 172 | + |
| 173 | +// This is needed to prevent the `mir_lower_std_lib` to crash the compiler |
| 174 | +impl MemoryBufferWrite for () { |
| 175 | + fn write_buf(self, mut writer: MemoryBufferWriter) {} |
| 176 | +} |
| 177 | + |
| 178 | +/// Memory buffer reader abstraction. |
| 179 | +pub struct MemoryBufferReader { |
| 180 | + buf: MemoryBuffer |
| 181 | + cur: Cursor |
| 182 | + |
| 183 | + /// Returns a new reader for the given buffer. |
| 184 | + pub fn new(buf: MemoryBuffer) -> Self { |
| 185 | + return MemoryBufferReader(buf, cur: Cursor::new(len: buf.len())) |
| 186 | + } |
| 187 | + |
| 188 | + /// The number of bytes remaining to be read. |
| 189 | + pub fn remainder(self) -> u256 { |
| 190 | + return self.cur.remainder() |
| 191 | + } |
| 192 | + |
| 193 | + fn read_offset(mut self, len: u256) -> u256 { |
| 194 | + return self.buf.offset() + self.cur.advance(len) |
| 195 | + } |
| 196 | + |
| 197 | + fn read_n(mut self, len: u256) -> u256 { |
| 198 | + let offset: u256 = self.read_offset(len) |
| 199 | + unsafe { |
| 200 | + let value: u256 = evm::mload(offset) |
| 201 | + return evm::shr(bits: 256 - len * 8, value) |
| 202 | + } |
| 203 | + } |
| 204 | + |
| 205 | + pub fn read_u8(mut self) -> u8 { |
| 206 | + return u8(self.read_n(len: 1)) |
| 207 | + } |
| 208 | + |
| 209 | + pub fn read_u16(mut self) -> u16 { |
| 210 | + return u16(self.read_n(len: 2)) |
| 211 | + } |
| 212 | + |
| 213 | + pub fn read_u32(mut self) -> u32 { |
| 214 | + return u32(self.read_n(len: 4)) |
| 215 | + } |
| 216 | + |
| 217 | + pub fn read_u64(mut self) -> u64 { |
| 218 | + return u64(self.read_n(len: 8)) |
| 219 | + } |
| 220 | + |
| 221 | + pub fn read_u128(mut self) -> u128 { |
| 222 | + return u128(self.read_n(len: 16)) |
| 223 | + } |
| 224 | + |
| 225 | + pub fn read_u256(mut self) -> u256 { |
| 226 | + let offset: u256 = self.read_offset(len: 32) |
| 227 | + unsafe { |
| 228 | + let value: u256 = evm::mload(offset) |
| 229 | + return value |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + pub fn read_buf(mut self, len: u256) -> MemoryBuffer { |
| 234 | + let mut buf: MemoryBuffer = MemoryBuffer::new(len) |
| 235 | + let mut writer: MemoryBufferWriter = buf.writer() |
| 236 | + |
| 237 | + while true { |
| 238 | + let bytes_remaining: u256 = writer.remainder() |
| 239 | + |
| 240 | + if bytes_remaining >= 32 { |
| 241 | + writer.write(value: self.read_u256()) |
| 242 | + } else if bytes_remaining == 0 { |
| 243 | + break |
| 244 | + } else { |
| 245 | + writer.write(value: self.read_u8()) |
| 246 | + } |
| 247 | + } |
| 248 | + |
| 249 | + return buf |
| 250 | + } |
| 251 | + |
| 252 | + // `T` has not been defined |
| 253 | + // pub fn read<T: MemoryBufferRead>(mut self) -> T { |
| 254 | + // T::read_buf(writer: self) |
| 255 | + // } |
| 256 | +} |
| 257 | + |
| 258 | +// pub trait MemoryBufferRead { |
| 259 | +// fn read_buf(self, mut reader: MemoryBufferReader) -> Self; |
| 260 | +// } |
| 261 | +// |
| 262 | +// impl MemoryBufferRead for u256 { .. } |
| 263 | +// . |
| 264 | +// . |
| 265 | +// impl MemoryBufferRead for u8 { .. } |
| 266 | + |
| 267 | +/// `MemoryBuffer` wrapper for raw calls to other contracts. |
| 268 | +pub struct RawCallBuffer { |
| 269 | + input_len: u256 |
| 270 | + output_len: u256 |
| 271 | + buf: MemoryBuffer |
| 272 | + |
| 273 | + pub fn new(input_len: u256, output_len: u256) -> Self { |
| 274 | + let len: u256 = math::max(input_len, output_len) |
| 275 | + let buf: MemoryBuffer = MemoryBuffer::new(len) |
| 276 | + |
| 277 | + return RawCallBuffer(input_len, output_len, buf) |
| 278 | + } |
| 279 | + |
| 280 | + pub fn input_len(self) -> u256 { |
| 281 | + return self.input_len |
| 282 | + } |
| 283 | + |
| 284 | + pub fn output_len(self) -> u256 { |
| 285 | + return self.output_len |
| 286 | + } |
| 287 | + |
| 288 | + pub fn offset(self) -> u256 { |
| 289 | + return self.buf.offset() |
| 290 | + } |
| 291 | + |
| 292 | + pub fn reader(self) -> MemoryBufferReader { |
| 293 | + return self.buf.reader() |
| 294 | + } |
| 295 | + |
| 296 | + pub fn writer(mut self) -> MemoryBufferWriter { |
| 297 | + return self.buf.writer() |
| 298 | + } |
| 299 | +} |
0 commit comments