@btc-vision/btc-runtime 1.3.20 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.3.20",
3
+ "version": "1.4.0",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "scripts": {
@@ -12,10 +12,11 @@ import { Revert } from '../types/Revert';
12
12
  import { SafeMath } from '../types/SafeMath';
13
13
 
14
14
  import { Calldata } from '../types';
15
- import { BOOLEAN_BYTE_LENGTH, U256_BYTE_LENGTH } from '../utils/lengths';
15
+ import { ADDRESS_BYTE_LENGTH, BOOLEAN_BYTE_LENGTH, U256_BYTE_LENGTH } from '../utils';
16
16
  import { IOP_20 } from './interfaces/IOP_20';
17
17
  import { OP20InitParameters } from './interfaces/OP20InitParameters';
18
18
  import { OP_NET } from './OP_NET';
19
+ import { sha256 } from '../env/global';
19
20
 
20
21
  const maxSupplyPointer: u16 = Blockchain.nextPointer;
21
22
  const decimalsPointer: u16 = Blockchain.nextPointer;
@@ -124,6 +125,23 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
124
125
  return response;
125
126
  }
126
127
 
128
+ public approveFrom(callData: Calldata): BytesWriter {
129
+ const response = new BytesWriter(BOOLEAN_BYTE_LENGTH);
130
+ const owner: Address = Blockchain.tx.origin;
131
+ const spender: Address = callData.readAddress();
132
+ const value: u256 = callData.readU256();
133
+
134
+ const signature = callData.readBytesWithLength();
135
+ if (signature.length !== 64) {
136
+ throw new Revert('Invalid signature length');
137
+ }
138
+
139
+ const resp = this._approveFrom(owner, spender, value, signature);
140
+ response.writeBoolean(resp);
141
+
142
+ return response;
143
+ }
144
+
127
145
  public balanceOf(callData: Calldata): BytesWriter {
128
146
  const response = new BytesWriter(U256_BYTE_LENGTH);
129
147
  const address: Address = callData.readAddress();
@@ -188,17 +206,19 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
188
206
  response = new BytesWriter(U256_BYTE_LENGTH);
189
207
  response.writeU256(this.maxSupply);
190
208
  break;
191
- case encodeSelector('allowance'):
209
+ case encodeSelector('allowance(address,address)'):
192
210
  return this.allowance(calldata);
193
- case encodeSelector('approve'):
211
+ case encodeSelector('approve(address,uint256)'):
194
212
  return this.approve(calldata);
195
- case encodeSelector('balanceOf'):
213
+ case encodeSelector('approveFrom(address,address,uint256,bytes)'):
214
+ return this.approveFrom(calldata);
215
+ case encodeSelector('balanceOf(address)'):
196
216
  return this.balanceOf(calldata);
197
- case encodeSelector('burn'):
217
+ case encodeSelector('burn(uint256)'):
198
218
  return this.burn(calldata);
199
- case encodeSelector('transfer'):
219
+ case encodeSelector('transfer(address,uint256)'):
200
220
  return this.transfer(calldata);
201
- case encodeSelector('transferFrom'):
221
+ case encodeSelector('transferFrom(address,address,uint256)'):
202
222
  return this.transferFrom(calldata);
203
223
  default:
204
224
  return super.execute(method, calldata);
@@ -214,6 +234,34 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
214
234
  return senderMap.get(spender);
215
235
  }
216
236
 
237
+ protected _approveFrom(owner: Address, spender: Address, value: u256, signature: Uint8Array): boolean {
238
+ if (owner === Blockchain.DEAD_ADDRESS) {
239
+ throw new Revert('Address can not be dead address');
240
+ }
241
+
242
+ if (spender === Blockchain.DEAD_ADDRESS) {
243
+ throw new Revert('Spender cannot be dead address');
244
+ }
245
+
246
+ // Regenerate the hash
247
+ const writer = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + U256_BYTE_LENGTH);
248
+ writer.writeAddress(owner);
249
+ writer.writeAddress(spender);
250
+ writer.writeU256(value);
251
+
252
+ const hash = sha256(writer.getBuffer());
253
+ if (!Blockchain.verifySchnorrSignature(owner, signature, hash)) {
254
+ throw new Revert('ApproveFrom: Invalid signature');
255
+ }
256
+
257
+ const senderMap = this.allowanceMap.get(owner);
258
+ senderMap.set(spender, value);
259
+
260
+ this.createApproveEvent(owner, spender, value);
261
+
262
+ return true;
263
+ }
264
+
217
265
  protected _approve(owner: Address, spender: Address, value: u256): boolean {
218
266
  if (owner === Blockchain.DEAD_ADDRESS) {
219
267
  throw new Revert('Address can not be dead address');
@@ -6,7 +6,7 @@ import { encodeSelector, Selector } from '../math/abi';
6
6
  import { Calldata } from '../types';
7
7
  import { Address } from '../types/Address';
8
8
  import { Revert } from '../types/Revert';
9
- import { ADDRESS_BYTE_LENGTH } from '../utils/lengths';
9
+ import { ADDRESS_BYTE_LENGTH } from '../utils';
10
10
 
11
11
  export class OP_NET implements IBTC {
12
12
  public get address(): Address {
@@ -17,9 +17,11 @@ export class OP_NET implements IBTC {
17
17
  return Blockchain.contractDeployer;
18
18
  }
19
19
 
20
- public onDeployment(_calldata: Calldata): void {}
20
+ public onDeployment(_calldata: Calldata): void {
21
+ }
21
22
 
22
- public onExecutionCompleted(): void {}
23
+ public onExecutionCompleted(): void {
24
+ }
23
25
 
24
26
  public execute(method: Selector, _calldata: Calldata): BytesWriter {
25
27
  let response: BytesWriter;