wormhole/staging/algorand/teal/pricekeeper/pricekeeper.teal

256 lines
4.3 KiB
Plaintext

#pragma version 5
// ================================================================================================
// PriceKeeper Approval Program
// ================================================================================================
//
// App-globals:
// sym : byte[] Symbol to keep price for
// vaddr : byte[] Validator account
// price : uint64 current price
// stdev : uint64 current confidence (standard deviation)
// slot : uint64 slot of this onchain publication
// exp : byte[] exponent. Interpret as two-compliment, Big-Endian 64bit
// ts : uint64 last timestamp
//
// Slots:
// 0 Input message block
// 1 SHA256-Hashed message
//
// The Message format must have the packed fields:
//
// Field size
// 9 header Literal "PRICEDATA"
// 1 version int8 (Must be 1)
// 8 dest This appId
// 16 symbol String filled with spaces e.g ("ALGO/USD ")
// 8 price Price. 64bit integer.
// 8 priceexp Price exponent. Interpret as two-compliment, Big-Endian 64bit
// 8 conf Confidence (stdev). 64bit integer.
// 8 slot Valid-slot of this aggregate price.
// 8 ts timestamp of this price submitted by PriceFetcher service
// 32 s Signature s-component
// 32 r Signature r-component
//
// Size: 138 bytes.
//
// ------------------------------------------------------------------------------------------------
// Application creation.
int 0
txn ApplicationID
==
bnz handle_create
// Handle app call: send price message
txn OnCompletion
int NoOp
==
bnz handle_call
// Handle deletion.
txn OnCompletion
int DeleteApplication
==
bnz success
// Fail otherwise
err
handle_create:
// -----------------------------------------------------
// Handle creation
// Arg 0: Validator address
// Arg 1: Symbol to keep price data
// -----------------------------------------------------
byte "vaddr"
txn ApplicationArgs 0
app_global_put
byte "sym"
txn ApplicationArgs 1
dup
len
int 16
==
assert
app_global_put
byte "ts"
global LatestTimestamp
app_global_put
b success
// -----------------------------------------------------
// Handle app call
// -----------------------------------------------------
handle_call:
// Group size must be 4 to raise computational allowance to 2800
global GroupSize
int 4
==
assert
// if this is one of dummy transactions(0, 1 or 2), exit with success
txn GroupIndex
int 3
!=
bnz success
// Verify if sender is the data validator
txn Sender
byte "vaddr"
app_global_get
==
assert
// Retrieve message, store in slot 0
txn ApplicationArgs 0
store 0
// ------------------------------------------------------
// Validate message
// ------------------------------------------------------
// Check length
load 0
len
int 138
==
assert
// Check header
byte "PRICEDATA"
load 0
extract 0 9
==
assert
// Check version - must be 1.
load 0
extract 9 1
byte 0x01
==
assert
// Check destination - must be this appId.
load 0
extract 10 8
btoi
txn ApplicationID
==
assert
// Reject zero price
load 0
extract 34 8
btoi
int 0
!=
assert
// Reject zero slot
load 0
extract 58 8
btoi
int 0
!=
assert
// Check timestamp:
// * must be higher than ts recorded in global state
// * must be lower than current block stamp + 10s
// (TODO: check this again)
load 0
extract 66 8
btoi
dup
dup
global LatestTimestamp
int 10
+
<
assert
byte "ts"
app_global_get
>
assert
// ed25519verify args in stack:
// data (hash of message)
load 0
extract 0 74
sha512_256
// (B) signature
load 0
extract 74 64
// validator-address
byte "vaddr"
app_global_get
// Verify signature
ed25519verify
int 1
==
assert
// ----------------------------------------------------------------------------
// Verified. Store data to app globals.
// ----------------------------------------------------------------------------
byte "ts"
load 0
extract 66 8
btoi
app_global_put
byte "price"
load 0
extract 34 8
btoi
app_global_put
byte "exp"
load 0
extract 42 8
app_global_put
byte "conf"
load 0
extract 50 8
btoi
app_global_put
byte "slot"
load 0
extract 58 8
btoi
app_global_put
b success
// ----------------------------------------------------------------------------
fail:
int 0
return
success:
int 1
return