0xa0::abi
This module implements ABI encoding/decoding methods for interoperability with EVM message format.
ABI Specification: https://docs.soliditylang.org/en/v0.8.26/abi-spec.html
AbiReader
AbiWriter
new_reader
new_writer
into_bytes
into_remaining_bytes
read_u256
read_u8
skip_slot
read_bytes
read_vector_u256
read_vector_bytes
write_u256
write_u8
write_bytes
write_vector_u256
write_vector_bytes
append_u256
append_bytes
decode_bytes
use 0x1::vector;
AbiReader
struct AbiReader has copy, drop
bytes: vector<u8>
head: u64
pos: u64
AbiWriter
struct AbiWriter has copy, drop
bytes: vector<u8>
pos: u64
new_reader
public fun new_reader(bytes: vector<u8>): abi::AbiReader
public fun new_reader(bytes: vector<u8>): AbiReader {
AbiReader {
bytes,
head: 0,
pos: 0,
}
}
new_writer
public fun new_writer(length: u64): abi::AbiWriter
public fun new_writer(length: u64): AbiWriter {
let mut bytes = vector[];
let mut i = 0;
while (i < 32 * length) {
bytes.push_back(0);
i = i + 1;
};
AbiWriter {
bytes,
pos: 0,
}
}
into_bytes
public fun into_bytes(self: abi::AbiWriter): vector<u8>
public fun into_bytes(self: AbiWriter): vector<u8> {
let AbiWriter { bytes, pos: _ } = self;
bytes
}
into_remaining_bytes
public fun into_remaining_bytes(self: abi::AbiReader): vector<u8>
public fun into_remaining_bytes(self: AbiReader): vector<u8> {
let AbiReader { bytes, head: _, pos: _ } = self;
bytes
}
read_u256
public fun read_u256(self: &mut abi::AbiReader): u256
public fun read_u256(self: &mut AbiReader): u256 {
let mut var = 0u256;
let mut i = 0;
let pos = self.pos;
while (i < 32) {
var = (var << 8) | (self.bytes[i + pos] as u256);
i = i + 1;
};
self.pos = pos + 32;
var
}
read_u8
public fun read_u8(self: &mut abi::AbiReader): u8
skip_slot
public fun skip_slot(self: &mut abi::AbiReader)
read_bytes
public fun read_bytes(self: &mut abi::AbiReader): vector<u8>
public fun read_bytes(self: &mut AbiReader): vector<u8> {
let pos = self.pos;
// Move position to the start of the bytes
let offset = self.read_u256() as u64;
self.pos = self.head + offset;
let var = self.decode_bytes();
// Move position to the next slot
self.pos = pos + 32;
var
}
read_vector_u256
public fun read_vector_u256(self: &mut abi::AbiReader): vector<u256>
public fun read_vector_u256(self: &mut AbiReader): vector<u256> {
let mut var = vector[];
let pos = self.pos;
// Move position to the start of the dynamic data
let offset = self.read_u256() as u64;
self.pos = self.head + offset;
let length = self.read_u256() as u64;
let mut i = 0;
while (i < length) {
var.push_back(self.read_u256());
i = i + 1;
};
self.pos = pos + 32;
var
}
read_vector_bytes
Decode ABI-encoded ‘bytes[]’
public fun read_vector_bytes(self: &mut abi::AbiReader): vector<vector<u8>>
public fun read_vector_bytes(self: &mut AbiReader): vector<vector<u8>> {
let mut var = vector[];
let pos = self.pos;
let head = self.head;
// Move position to the start of the dynamic data
let offset = self.read_u256() as u64;
self.pos = head + offset;
let length = self.read_u256() as u64;
self.head = self.pos;
let mut i = 0;
while (i < length) {
var.push_back(self.read_bytes());
i = i + 1;
};
// Move position to the next slot
self.pos = pos + 32;
self.head = head;
var
}
write_u256
public fun write_u256(self: &mut abi::AbiWriter, var: u256): &mut abi::AbiWriter
public fun write_u256(self: &mut AbiWriter, var: u256): &mut AbiWriter {
let pos = self.pos;
let mut i = 0;
while (i < 32) {
let exp = ((31 - i) * 8 as u8);
let byte = (var >> exp & 255 as u8);
*&mut self.bytes[i + pos] = byte;
i = i + 1;
};
self.pos = pos + 32;
self
}
write_u8
public fun write_u8(self: &mut abi::AbiWriter, var: u8): &mut abi::AbiWriter
public fun write_u8(self: &mut AbiWriter, var: u8): &mut AbiWriter {
self.write_u256(var as u256)
}
write_bytes
public fun write_bytes(self: &mut abi::AbiWriter, var: vector<u8>): &mut abi::AbiWriter
public fun write_bytes(self: &mut AbiWriter, var: vector<u8>): &mut AbiWriter {
let offset = self.bytes.length() as u256;
self.write_u256(offset);
// Write dynamic data length and bytes at the tail
self.append_u256(var.length() as u256);
self.append_bytes(var);
self
}
write_vector_u256
public fun write_vector_u256(self: &mut abi::AbiWriter, var: vector<u256>): &mut abi::AbiWriter
public fun write_vector_u256(
self: &mut AbiWriter,
var: vector<u256>,
): &mut AbiWriter {
let offset = self.bytes.length() as u256;
self.write_u256(offset);
let length = var.length();
self.append_u256(length as u256);
let mut i = 0;
while (i < length) {
self.append_u256(var[i]);
i = i + 1;
};
self
}
write_vector_bytes
public fun write_vector_bytes(self: &mut abi::AbiWriter, var: vector<vector<u8>>): &mut abi::AbiWriter
public fun write_vector_bytes(
self: &mut AbiWriter,
var: vector<vector<u8>>,
): &mut AbiWriter {
let offset = self.bytes.length() as u256;
self.write_u256(offset);
let length = var.length();
self.append_u256(length as u256);
let mut writer = new_writer(length);
let mut i = 0;
while (i < length) {
writer.write_bytes(var[i]);
i = i + 1;
};
self.append_bytes(writer.into_bytes());
self
}
append_u256
fun append_u256(self: &mut abi::AbiWriter, var: u256)
fun append_u256(self: &mut AbiWriter, var: u256) {
let mut i = 0;
while (i < 32) {
self.bytes.push_back(((var >> ((31 - i) * 8 as u8)) & 255 as u8));
i = i + 1;
};
}
append_bytes
fun append_bytes(self: &mut abi::AbiWriter, var: vector<u8>)
fun append_bytes(self: &mut AbiWriter, var: vector<u8>) {
let length = var.length();
if (length == 0) {
return
};
self.bytes.append(var);
let mut i = 0u64;
while (i < 31 - (length - 1) % 32) {
self.bytes.push_back(0);
i = i + 1;
};
}
decode_bytes
fun decode_bytes(self: &mut abi::AbiReader): vector<u8>
fun decode_bytes(self: &mut AbiReader): vector<u8> {
let length = self.read_u256() as u64;
let pos = self.pos;
let mut bytes = vector[];
let mut i = 0;
while (i < length) {
bytes.push_back(self.bytes[i + pos]);
i = i + 1;
};
bytes
}