@btc-vision/btc-runtime 1.3.20 → 1.3.21

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.3.21",
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();
@@ -192,6 +210,8 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
192
210
  return this.allowance(calldata);
193
211
  case encodeSelector('approve'):
194
212
  return this.approve(calldata);
213
+ case encodeSelector('approveFrom'):
214
+ return this.approveFrom(calldata);
195
215
  case encodeSelector('balanceOf'):
196
216
  return this.balanceOf(calldata);
197
217
  case encodeSelector('burn'):
@@ -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');