@btc-vision/btc-runtime
Version:
Bitcoin Smart Contract Runtime
259 lines (190 loc) • 5.61 kB
text/typescript
import { u256 } from '@btc-vision/as-bignum/assembly';
import { Blockchain } from '../env';
import { encodePointer } from '../math/abi';
import { SafeMath } from '../types/SafeMath';
export class StoredU256 {
private readonly pointerBuffer: Uint8Array;
constructor(
public pointer: u16,
public subPointer: Uint8Array,
) {
assert(subPointer.length <= 30, `You must pass a 30 bytes sub-pointer. (Address, got ${subPointer.length})`);
this.pointerBuffer = encodePointer(pointer, subPointer);
}
private _value: u256 = u256.Zero;
public get value(): u256 {
this.ensureValue();
return this._value;
}
public set value(value: u256) {
if (u256.eq(value, this._value)) {
return;
}
this._value = value;
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
}
public get toBytes(): Uint8Array {
return this._value.toUint8Array(true);
}
private get __value(): Uint8Array {
return this._value.toUint8Array(true);
}
public toString(): string {
return this._value.toString();
}
public add(value: u256): this {
this.ensureValue();
this._value = SafeMath.add(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public addNoCommit(value: u256): this {
this._value = SafeMath.add(this._value, value);
return this;
}
public subNoCommit(value: u256): this {
this._value = SafeMath.sub(this._value, value);
return this;
}
public commit(): this {
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public sub(value: u256): this {
this.ensureValue();
this._value = SafeMath.sub(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public mul(value: u256): this {
this.ensureValue();
this._value = SafeMath.mul(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public eq(value: u256): boolean {
this.ensureValue();
return this._value === value;
}
public ne(value: u256): boolean {
this.ensureValue();
return this._value !== value;
}
public lt(value: u256): boolean {
this.ensureValue();
return this._value < value;
}
public gt(value: u256): boolean {
this.ensureValue();
return this._value > value;
}
public le(value: u256): boolean {
this.ensureValue();
return this._value <= value;
}
public ge(value: u256): boolean {
this.ensureValue();
return this._value >= value;
}
public shr(value: i32): this {
this.ensureValue();
this._value = u256.shr(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public and(value: u256): this {
this.ensureValue();
this._value = u256.and(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public or(value: u256): this {
this.ensureValue();
this._value = u256.or(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public xor(value: u256): this {
this.ensureValue();
this._value = u256.xor(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public pow(exponent: u256): this {
this.ensureValue();
this._value = SafeMath.pow(this._value, exponent);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public mod(value: u256): this {
this.ensureValue();
this._value = SafeMath.mod(this._value, value);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
.postfix('++')
public inc(): this {
this.ensureValue();
this._value = SafeMath.add(this._value, u256.One);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
.postfix('--')
public dec(): this {
this.ensureValue();
this._value = SafeMath.sub(this._value, u256.One);
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public set(value: u256): this {
this._value = value;
Blockchain.setStorageAt(this.pointerBuffer, this.__value);
return this;
}
public toUint8Array(): Uint8Array {
return this._value.toUint8Array(true);
}
private ensureValue(): void {
const value = Blockchain.getStorageAt(this.pointerBuffer);
this._value = u256.fromUint8ArrayBE(value);
}
}