2022-04-29 12:53:48 -07:00
#!/usr/bin/python3
"""
Copyright 2022 Wormhole Project Contributors
Licensed under the Apache License , Version 2.0 ( the " License " ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : / / www . apache . org / licenses / LICENSE - 2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an " AS IS " BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
"""
from typing import List , Tuple , Dict , Any , Optional , Union
from pyteal . ast import *
from pyteal . types import *
from pyteal . compiler import *
from pyteal . ir import *
from globals import *
from inlineasm import *
from algosdk . v2client . algod import AlgodClient
from TmplSig import TmplSig
from local_blob import LocalBlob
import pprint
import sys
max_keys = 15
max_bytes_per_key = 127
bits_per_byte = 8
bits_per_key = max_bytes_per_key * bits_per_byte
max_bytes = max_bytes_per_key * max_keys
max_bits = bits_per_byte * max_bytes
2022-05-13 12:45:25 -07:00
portal_transfer_selector = MethodSignature ( " portal_transfer(byte[])byte[] " )
2022-05-05 06:23:42 -07:00
def fullyCompileContract ( genTeal , client : AlgodClient , contract : Expr , name , devmode ) - > bytes :
if devmode :
teal = compileTeal ( contract , mode = Mode . Application , version = 6 , assembleConstants = True )
else :
teal = compileTeal ( contract , mode = Mode . Application , version = 6 , assembleConstants = True , optimize = OptimizeOptions ( scratch_slots = True ) )
2022-04-29 12:53:48 -07:00
if genTeal :
with open ( name , " w " ) as f :
print ( " Writing " + name )
f . write ( teal )
else :
with open ( name , " r " ) as f :
print ( " Reading " + name )
teal = f . read ( )
response = client . compile ( teal )
return response
def clear_token_bridge ( ) :
return Int ( 1 )
def approve_token_bridge ( seed_amt : int , tmpl_sig : TmplSig , devMode : bool ) :
blob = LocalBlob ( )
tidx = ScratchVar ( )
mfee = ScratchVar ( )
def MagicAssert ( a ) - > Expr :
if devMode :
from inspect import currentframe
return Assert ( And ( a , Int ( currentframe ( ) . f_back . f_lineno ) ) )
else :
return Assert ( a )
@Subroutine ( TealType . uint64 )
def governanceSet ( ) - > Expr :
maybe = App . globalGetEx ( App . globalGet ( Bytes ( " coreid " ) ) , Bytes ( " currentGuardianSetIndex " ) )
return Seq ( maybe , MagicAssert ( maybe . hasValue ( ) ) , maybe . value ( ) )
@Subroutine ( TealType . uint64 )
def getMessageFee ( ) - > Expr :
maybe = App . globalGetEx ( App . globalGet ( Bytes ( " coreid " ) ) , Bytes ( " MessageFee " ) )
return Seq ( maybe , MagicAssert ( maybe . hasValue ( ) ) , maybe . value ( ) )
@Subroutine ( TealType . bytes )
2022-05-06 11:37:31 -07:00
def getAppAddress ( appid : Expr ) - > Expr :
maybe = AppParam . address ( appid )
2022-04-29 12:53:48 -07:00
return Seq ( maybe , MagicAssert ( maybe . hasValue ( ) ) , maybe . value ( ) )
def assert_common_checks ( e ) - > Expr :
return MagicAssert ( And (
e . rekey_to ( ) == Global . zero_address ( ) ,
e . close_remainder_to ( ) == Global . zero_address ( ) ,
e . asset_close_to ( ) == Global . zero_address ( )
) )
@Subroutine ( TealType . none )
def checkFeePmt ( off : Expr ) :
return Seq ( [
If ( mfee . load ( ) > Int ( 0 ) , Seq ( [
tidx . store ( Txn . group_index ( ) - off ) ,
MagicAssert ( And (
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . Payment ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
Gtxn [ tidx . load ( ) ] . receiver ( ) == Global . current_application_address ( ) ,
Gtxn [ tidx . load ( ) ] . amount ( ) > = mfee . load ( )
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] )
] ) )
] )
@Subroutine ( TealType . none )
def sendMfee ( ) :
return Seq ( [
If ( mfee . load ( ) > Int ( 0 ) , Seq ( [
InnerTxnBuilder . SetFields (
{
TxnField . type_enum : TxnType . Payment ,
TxnField . receiver : App . globalGet ( Bytes ( " coreAddr " ) ) ,
TxnField . amount : mfee . load ( ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
InnerTxnBuilder . Next ( ) ,
] ) ) ,
] )
@Subroutine ( TealType . bytes )
def encode_uvarint ( val : Expr , b : Expr ) :
buff = ScratchVar ( )
return Seq (
buff . store ( b ) ,
Concat (
buff . load ( ) ,
If (
val > = Int ( 128 ) ,
encode_uvarint (
val >> Int ( 7 ) ,
Extract ( Itob ( ( val & Int ( 255 ) ) | Int ( 128 ) ) , Int ( 7 ) , Int ( 1 ) ) ,
) ,
Extract ( Itob ( val & Int ( 255 ) ) , Int ( 7 ) , Int ( 1 ) ) ,
) ,
) ,
)
@Subroutine ( TealType . bytes )
def trim_bytes ( str : Expr ) :
len = ScratchVar ( )
off = ScratchVar ( )
zero = ScratchVar ( )
r = ScratchVar ( )
return Seq ( [
r . store ( str ) ,
len . store ( Len ( r . load ( ) ) ) ,
zero . store ( BytesZero ( Int ( 1 ) ) ) ,
off . store ( Int ( 0 ) ) ,
While ( off . load ( ) < len . load ( ) ) . Do ( Seq ( [
If ( Extract ( r . load ( ) , off . load ( ) , Int ( 1 ) ) == zero . load ( ) ) . Then ( Seq ( [
r . store ( Extract ( r . load ( ) , Int ( 0 ) , off . load ( ) ) ) ,
off . store ( len . load ( ) )
] ) ) ,
off . store ( off . load ( ) + Int ( 1 ) )
] ) ) ,
r . load ( )
] )
@Subroutine ( TealType . uint64 )
def getFactor ( dec : Expr ) :
return Cond (
[ dec == Int ( 9 ) , Int ( 10 ) ] ,
[ dec == Int ( 10 ) , Int ( 100 ) ] ,
[ dec == Int ( 11 ) , Int ( 1000 ) ] ,
[ dec == Int ( 12 ) , Int ( 10000 ) ] ,
[ dec == Int ( 13 ) , Int ( 100000 ) ] ,
[ dec == Int ( 14 ) , Int ( 1000000 ) ] ,
[ dec == Int ( 15 ) , Int ( 10000000 ) ] ,
[ dec == Int ( 16 ) , Int ( 100000000 ) ] ,
[ dec > Int ( 16 ) , Seq ( Reject ( ) , Int ( 1 ) ) ] ,
[ dec < Int ( 9 ) , Int ( 1 ) ]
)
@Subroutine ( TealType . bytes )
def get_sig_address ( acct_seq_start : Expr , emitter : Expr ) :
# We could iterate over N items and encode them for a more general interface
# but we inline them directly here
return Sha512_256 (
Concat (
Bytes ( " Program " ) ,
# ADDR_IDX aka sequence start
tmpl_sig . get_bytecode_chunk ( 0 ) ,
encode_uvarint ( acct_seq_start , Bytes ( " " ) ) ,
# EMMITTER_ID
tmpl_sig . get_bytecode_chunk ( 1 ) ,
encode_uvarint ( Len ( emitter ) , Bytes ( " " ) ) ,
emitter ,
# APP_ID
tmpl_sig . get_bytecode_chunk ( 2 ) ,
encode_uvarint ( Global . current_application_id ( ) , Bytes ( " " ) ) ,
# TMPL_APP_ADDRESS
tmpl_sig . get_bytecode_chunk ( 3 ) ,
encode_uvarint ( Len ( Global . current_application_address ( ) ) , Bytes ( " " ) ) ,
Global . current_application_address ( ) ,
tmpl_sig . get_bytecode_chunk ( 4 ) ,
)
)
def governance ( ) :
off = ScratchVar ( )
a = ScratchVar ( )
targetChain = ScratchVar ( )
chain = ScratchVar ( )
emitter = ScratchVar ( )
set = ScratchVar ( )
idx = ScratchVar ( )
verifyIdx = ScratchVar ( )
verifyVAA = Gtxn [ verifyIdx . load ( ) ]
return Seq ( [
checkForDuplicate ( ) ,
# All governance must be done with the most recent guardian set...
set . store ( governanceSet ( ) ) ,
idx . store ( Extract ( Txn . application_args [ 1 ] , Int ( 1 ) , Int ( 4 ) ) ) ,
MagicAssert ( Btoi ( idx . load ( ) ) == set . load ( ) ) ,
# The offset of the chain
off . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , Int ( 5 ) , Int ( 1 ) ) ) * Int ( 66 ) + Int ( 14 ) ) ,
verifyIdx . store ( Txn . group_index ( ) - Int ( 1 ) ) ,
MagicAssert ( And (
# Did verifyVAA pass?
verifyVAA . type_enum ( ) == TxnType . ApplicationCall ,
verifyVAA . application_id ( ) == App . globalGet ( Bytes ( " coreid " ) ) ,
verifyVAA . application_args [ 0 ] == Bytes ( " verifyVAA " ) ,
verifyVAA . sender ( ) == Txn . sender ( ) ,
# Lets see if the vaa we are about to process was actually verified by the core
verifyVAA . application_args [ 1 ] == Txn . application_args [ 1 ] ,
# We all opted into the same accounts?
verifyVAA . accounts [ 0 ] == Txn . accounts [ 0 ] ,
verifyVAA . accounts [ 1 ] == Txn . accounts [ 1 ] ,
verifyVAA . accounts [ 2 ] == Txn . accounts [ 2 ] ,
# Better be the right emitters
Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 2 ) ) == Bytes ( " base16 " , " 0001 " ) ,
Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 2 ) , Int ( 32 ) ) == Concat ( BytesZero ( Int ( 31 ) ) , Bytes ( " base16 " , " 04 " ) ) ,
) ) ,
assert_common_checks ( verifyVAA ) ,
assert_common_checks ( Txn ) ,
# correct module?
MagicAssert ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 43 ) , Int ( 32 ) ) == Concat ( BytesZero ( Int ( 21 ) ) , Bytes ( " base16 " , " 546f6b656e427269646765 " ) ) ) ,
a . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 75 ) , Int ( 1 ) ) ) ) ,
off . store ( off . load ( ) + Int ( 76 ) ) ,
Cond (
[ a . load ( ) == Int ( 1 ) , Seq ( [
targetChain . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 2 ) ) ) ) ,
MagicAssert ( Or ( ( targetChain . load ( ) == Int ( 0 ) ) , ( targetChain . load ( ) == Int ( 8 ) ) ) ) ,
chain . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 2 ) , Int ( 2 ) ) ) ,
emitter . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 4 ) , Int ( 32 ) ) ) ,
# Can I only register once? Rumor says yes
MagicAssert ( App . globalGet ( Concat ( Bytes ( " Chain " ) , chain . load ( ) ) ) == Int ( 0 ) ) ,
App . globalPut ( Concat ( Bytes ( " Chain " ) , chain . load ( ) ) , emitter . load ( ) ) ,
] ) ] ,
[ a . load ( ) == Int ( 2 ) , Seq ( [
MagicAssert ( Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 2 ) ) == Bytes ( " base16 " , " 0008 " ) ) ,
App . globalPut ( Bytes ( " validUpdateApproveHash " ) , Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 2 ) , Int ( 32 ) ) )
] ) ]
) ,
Approve ( )
] )
def receiveAttest ( ) :
me = Global . current_application_address ( )
off = ScratchVar ( )
Address = ScratchVar ( )
Chain = ScratchVar ( )
FromChain = ScratchVar ( )
Decimals = ScratchVar ( )
Symbol = ScratchVar ( )
Name = ScratchVar ( )
asset = ScratchVar ( )
buf = ScratchVar ( )
c = ScratchVar ( )
a = ScratchVar ( )
return Seq ( [
checkForDuplicate ( ) ,
tidx . store ( Txn . group_index ( ) - Int ( 4 ) ) ,
MagicAssert ( And (
# Lets see if the vaa we are about to process was actually verified by the core
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . ApplicationCall ,
Gtxn [ tidx . load ( ) ] . application_id ( ) == App . globalGet ( Bytes ( " coreid " ) ) ,
Gtxn [ tidx . load ( ) ] . application_args [ 0 ] == Bytes ( " verifyVAA " ) ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
# we are all taking about the same vaa?
Gtxn [ tidx . load ( ) ] . application_args [ 1 ] == Txn . application_args [ 1 ] ,
# We all opted into the same accounts?
Gtxn [ tidx . load ( ) ] . accounts [ 0 ] == Txn . accounts [ 0 ] ,
Gtxn [ tidx . load ( ) ] . accounts [ 1 ] == Txn . accounts [ 1 ] ,
Gtxn [ tidx . load ( ) ] . accounts [ 2 ] == Txn . accounts [ 2 ] ,
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] ) ,
tidx . store ( Txn . group_index ( ) - Int ( 3 ) ) ,
MagicAssert ( And (
# Did the user pay the lsig to attest a new product?
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . Payment ,
Gtxn [ tidx . load ( ) ] . amount ( ) > = Int ( 100000 ) ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
Gtxn [ tidx . load ( ) ] . receiver ( ) == Txn . accounts [ 3 ] ,
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] ) ,
tidx . store ( Txn . group_index ( ) - Int ( 2 ) ) ,
MagicAssert ( And (
# We had to buy some extra CPU
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . ApplicationCall ,
Gtxn [ tidx . load ( ) ] . application_id ( ) == Global . current_application_id ( ) ,
Gtxn [ tidx . load ( ) ] . application_args [ 0 ] == Bytes ( " nop " ) ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] ) ,
tidx . store ( Txn . group_index ( ) - Int ( 1 ) ) ,
MagicAssert ( And (
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . ApplicationCall ,
Gtxn [ tidx . load ( ) ] . application_id ( ) == Global . current_application_id ( ) ,
Gtxn [ tidx . load ( ) ] . application_args [ 0 ] == Bytes ( " nop " ) ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
( Global . group_size ( ) - Int ( 1 ) ) == Txn . group_index ( ) # This should be the last entry...
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] ) ,
off . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , Int ( 5 ) , Int ( 1 ) ) ) * Int ( 66 ) + Int ( 6 ) + Int ( 8 ) ) , # The offset of the chain
Chain . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 2 ) ) ) ) ,
# Make sure that the emitter on the sending chain is correct for the token bridge
MagicAssert ( App . globalGet ( Concat ( Bytes ( " Chain " ) , Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 2 ) ) ) )
== Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 2 ) , Int ( 32 ) ) ) ,
off . store ( off . load ( ) + Int ( 43 ) ) ,
MagicAssert ( Int ( 2 ) == Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 1 ) ) ) ) ,
Address . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 1 ) , Int ( 32 ) ) ) ,
FromChain . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 33 ) , Int ( 2 ) ) ) ) ,
Decimals . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 35 ) , Int ( 1 ) ) ) ) ,
Symbol . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 36 ) , Int ( 32 ) ) ) ,
Name . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 68 ) , Int ( 32 ) ) ) ,
# Lets trim this... seems these are limited to 7 characters
Symbol . store ( trim_bytes ( Symbol . load ( ) ) ) ,
If ( Len ( Symbol . load ( ) ) > Int ( 7 ) , Symbol . store ( Extract ( Symbol . load ( ) , Int ( 0 ) , Int ( 7 ) ) ) ) ,
2022-04-29 18:19:30 -07:00
Name . store ( Concat ( trim_bytes ( Name . load ( ) ) , Bytes ( " (Wormhole) " ) ) ) ,
2022-04-29 12:53:48 -07:00
# Due to constrains on some supported chains, all token
# amounts passed through the token bridge are truncated to
# a maximum of 8 decimals.
#
# Any chains implementation must make sure that of any
# token only ever MaxUint64 units (post-shifting) are
# bridged into the wormhole network at any given time (all
# target chains combined), even tough the slot is 32 bytes
# long (theoretically fitting uint256).
If ( Decimals . load ( ) > Int ( 8 ) , Decimals . store ( Int ( 8 ) ) ) ,
# This confirms the user gave us access to the correct memory for this asset..
MagicAssert ( Txn . accounts [ 3 ] == get_sig_address ( FromChain . load ( ) , Address . load ( ) ) ) ,
# Lets see if we've seen this asset before
asset . store ( blob . read ( Int ( 3 ) , Int ( 0 ) , Int ( 8 ) ) ) ,
# The # offset to the digest
off . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , Int ( 5 ) , Int ( 1 ) ) ) * Int ( 66 ) + Int ( 6 ) ) ,
# New asset
If ( asset . load ( ) == Itob ( Int ( 0 ) ) ) . Then ( Seq ( [
InnerTxnBuilder . Begin ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . sender : Txn . accounts [ 3 ] ,
TxnField . type_enum : TxnType . AssetConfig ,
TxnField . config_asset_name : Name . load ( ) ,
TxnField . config_asset_unit_name : Symbol . load ( ) ,
TxnField . config_asset_total : Int ( 18446744073709551614 ) ,
TxnField . config_asset_decimals : Decimals . load ( ) ,
TxnField . config_asset_manager : me ,
TxnField . config_asset_reserve : me ,
# We cannot freeze or clawback assets... per the spirit of
TxnField . config_asset_freeze : Global . zero_address ( ) ,
TxnField . config_asset_clawback : Global . zero_address ( ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
InnerTxnBuilder . Submit ( ) ,
asset . store ( Itob ( InnerTxn . created_asset_id ( ) ) ) ,
Pop ( blob . write ( Int ( 3 ) , Int ( 0 ) , asset . load ( ) ) ) ,
blob . meta ( Int ( 3 ) , Bytes ( " asset " ) )
] ) ) ,
# We save away the entire digest that created this asset in case we ever need to reproduce it while sending this
# coin to another chain
buf . store ( Txn . application_args [ 1 ] ) ,
Pop ( blob . write ( Int ( 3 ) , Int ( 8 ) , Extract ( buf . load ( ) , off . load ( ) , Len ( buf . load ( ) ) - off . load ( ) ) ) ) ,
Approve ( )
] )
def completeTransfer ( ) :
me = Global . current_application_address ( )
off = ScratchVar ( )
Chain = ScratchVar ( )
Emitter = ScratchVar ( )
Amount = ScratchVar ( )
Origin = ScratchVar ( )
OriginChain = ScratchVar ( )
Destination = ScratchVar ( )
DestChain = ScratchVar ( )
Fee = ScratchVar ( )
asset = ScratchVar ( )
factor = ScratchVar ( )
d = ScratchVar ( )
zb = ScratchVar ( )
action = ScratchVar ( )
2022-05-06 11:37:31 -07:00
aid = ScratchVar ( )
2022-04-29 12:53:48 -07:00
return Seq ( [
checkForDuplicate ( ) ,
zb . store ( BytesZero ( Int ( 32 ) ) ) ,
tidx . store ( Txn . group_index ( ) - Int ( 1 ) ) ,
MagicAssert ( And (
# Lets see if the vaa we are about to process was actually verified by the core
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . ApplicationCall ,
Gtxn [ tidx . load ( ) ] . application_id ( ) == App . globalGet ( Bytes ( " coreid " ) ) ,
Gtxn [ tidx . load ( ) ] . application_args [ 0 ] == Bytes ( " verifyVAA " ) ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
# Lets see if the vaa we are about to process was actually verified by the core
Gtxn [ tidx . load ( ) ] . application_args [ 1 ] == Txn . application_args [ 1 ] ,
# We all opted into the same accounts?
Gtxn [ tidx . load ( ) ] . accounts [ 0 ] == Txn . accounts [ 0 ] ,
Gtxn [ tidx . load ( ) ] . accounts [ 1 ] == Txn . accounts [ 1 ] ,
Gtxn [ tidx . load ( ) ] . accounts [ 2 ] == Txn . accounts [ 2 ]
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] ) ,
assert_common_checks ( Txn ) ,
off . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , Int ( 5 ) , Int ( 1 ) ) ) * Int ( 66 ) + Int ( 6 ) + Int ( 8 ) ) , # The offset of the chain
Chain . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 2 ) ) ) ) ,
Emitter . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 2 ) , Int ( 32 ) ) ) ,
# We coming from the correct emitter on the sending chain for the token bridge
# ... This is 90% of the security...
If ( Chain . load ( ) == Int ( 8 ) ,
MagicAssert ( Global . current_application_address ( ) == Emitter . load ( ) ) , # This came from us?
MagicAssert ( App . globalGet ( Concat ( Bytes ( " Chain " ) , Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 2 ) ) ) ) == Emitter . load ( ) ) ) ,
off . store ( off . load ( ) + Int ( 43 ) ) ,
# This is a transfer message... right?
action . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 1 ) ) ) ) ,
MagicAssert ( Or ( action . load ( ) == Int ( 1 ) , action . load ( ) == Int ( 3 ) ) ) ,
MagicAssert ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 1 ) , Int ( 24 ) ) == Extract ( zb . load ( ) , Int ( 0 ) , Int ( 24 ) ) ) ,
Amount . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 25 ) , Int ( 8 ) ) ) ) , # uint256
Origin . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 33 ) , Int ( 32 ) ) ) ,
OriginChain . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 65 ) , Int ( 2 ) ) ) ) ,
Destination . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 67 ) , Int ( 32 ) ) ) ,
DestChain . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 99 ) , Int ( 2 ) ) ) ) ,
# This directed at us?
MagicAssert ( DestChain . load ( ) == Int ( 8 ) ) ,
If ( action . load ( ) == Int ( 3 ) , Seq ( [
2022-05-06 11:37:31 -07:00
aid . store ( Btoi ( Extract ( Destination . load ( ) , Int ( 24 ) , Int ( 8 ) ) ) ) , # The destination is the appid in a payload3
2022-04-29 12:53:48 -07:00
tidx . store ( Txn . group_index ( ) + Int ( 1 ) ) ,
MagicAssert ( And (
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . ApplicationCall ,
2022-05-13 12:45:25 -07:00
Gtxn [ tidx . load ( ) ] . application_args [ 0 ] == portal_transfer_selector , # sha256("portal_transfer(byte[])byte[]")[:4]
Gtxn [ tidx . load ( ) ] . application_args [ 1 ] == Concat ( Extract ( Itob ( Len ( Txn . application_args [ 1 ] ) ) , Int ( 6 ) , Int ( 2 ) ) , Txn . application_args [ 1 ] ) ,
2022-05-06 11:37:31 -07:00
Gtxn [ tidx . load ( ) ] . application_id ( ) == aid . load ( )
2022-04-29 12:53:48 -07:00
) ) ,
2022-05-23 12:22:40 -07:00
Destination . store ( getAppAddress ( aid . load ( ) ) ) ,
Fee . store ( Int ( 0 ) )
] ) , Seq ( [
MagicAssert ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 101 ) , Int ( 24 ) ) == Extract ( zb . load ( ) , Int ( 0 ) , Int ( 24 ) ) ) ,
Fee . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 125 ) , Int ( 8 ) ) ) ) , # uint256
MagicAssert ( Fee . load ( ) < = Amount . load ( ) ) ,
# Remove the fee
Amount . store ( Amount . load ( ) - Fee . load ( ) ) ,
] )
) ,
2022-04-29 12:53:48 -07:00
If ( OriginChain . load ( ) == Int ( 8 ) ,
Seq ( [
asset . store ( Btoi ( Extract ( Origin . load ( ) , Int ( 24 ) , Int ( 8 ) ) ) ) ,
MagicAssert ( Txn . accounts [ 3 ] == get_sig_address ( asset . load ( ) , Bytes ( " native " ) ) ) ,
# Now, the horrible part... we have to scale the amount back out to compensate for the "dedusting"
# when this was sent...
If ( asset . load ( ) == Int ( 0 ) ,
Seq ( [
InnerTxnBuilder . Begin ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . sender : Txn . accounts [ 3 ] ,
TxnField . type_enum : TxnType . Payment ,
TxnField . receiver : Destination . load ( ) ,
TxnField . amount : Amount . load ( ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
If ( Fee . load ( ) > Int ( 0 ) , Seq ( [
InnerTxnBuilder . Next ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . sender : Txn . accounts [ 3 ] ,
TxnField . type_enum : TxnType . Payment ,
TxnField . receiver : Txn . sender ( ) ,
TxnField . amount : Fee . load ( ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
] ) ) ,
InnerTxnBuilder . Submit ( ) ,
Approve ( )
] ) , # End of special case for algo
Seq ( [ # Start of handling code for algorand tokens
factor . store ( getFactor ( Btoi ( extract_decimal ( asset . load ( ) ) ) ) ) ,
If ( factor . load ( ) != Int ( 1 ) ,
Seq ( [
Amount . store ( Amount . load ( ) * factor . load ( ) ) ,
Fee . store ( Fee . load ( ) * factor . load ( ) )
] )
) , # If(factor.load() != Int(1),
] ) # End of handling code for algorand tokens
) , # If(asset.load() == Int(0),
] ) , # If(OriginChain.load() == Int(8),
# OriginChain.load() != Int(8),
Seq ( [
# Lets see if we've seen this asset before
asset . store ( Btoi ( blob . read ( Int ( 3 ) , Int ( 0 ) , Int ( 8 ) ) ) ) ,
MagicAssert ( And (
asset . load ( ) != Int ( 0 ) ,
Txn . accounts [ 3 ] == get_sig_address ( OriginChain . load ( ) , Origin . load ( ) )
)
) ,
] ) # OriginChain.load() != Int(8),
) , # If(OriginChain.load() == Int(8)
# Actually send the coins...
# Log(Bytes("Main")),
InnerTxnBuilder . Begin ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . sender : Txn . accounts [ 3 ] ,
TxnField . type_enum : TxnType . AssetTransfer ,
TxnField . xfer_asset : asset . load ( ) ,
TxnField . asset_amount : Amount . load ( ) ,
TxnField . asset_receiver : Destination . load ( ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
If ( Fee . load ( ) > Int ( 0 ) , Seq ( [
# Log(Bytes("Fees")),
InnerTxnBuilder . Next ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . sender : Txn . accounts [ 3 ] ,
TxnField . type_enum : TxnType . AssetTransfer ,
TxnField . xfer_asset : asset . load ( ) ,
TxnField . asset_amount : Fee . load ( ) ,
TxnField . asset_receiver : Txn . sender ( ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
] ) ) ,
InnerTxnBuilder . Submit ( ) ,
Approve ( )
] )
METHOD = Txn . application_args [ 0 ]
on_delete = Seq ( [ Reject ( ) ] )
@Subroutine ( TealType . bytes )
def auth_addr ( id ) - > Expr :
maybe = AccountParam . authAddr ( id )
return Seq ( maybe , If ( maybe . hasValue ( ) , maybe . value ( ) , Bytes ( " " ) ) )
@Subroutine ( TealType . bytes )
def extract_name ( id ) - > Expr :
maybe = AssetParam . name ( id )
return Seq ( maybe , If ( maybe . hasValue ( ) , maybe . value ( ) , Bytes ( " " ) ) )
@Subroutine ( TealType . bytes )
def extract_creator ( id ) - > Expr :
maybe = AssetParam . creator ( id )
return Seq ( maybe , If ( maybe . hasValue ( ) , maybe . value ( ) , Bytes ( " " ) ) )
@Subroutine ( TealType . bytes )
def extract_unit_name ( id ) - > Expr :
maybe = AssetParam . unitName ( id )
return Seq ( maybe , If ( maybe . hasValue ( ) , maybe . value ( ) , Bytes ( " " ) ) )
@Subroutine ( TealType . bytes )
def extract_decimal ( id ) - > Expr :
maybe = AssetParam . decimals ( id )
return Seq ( maybe , If ( maybe . hasValue ( ) , Extract ( Itob ( maybe . value ( ) ) , Int ( 7 ) , Int ( 1 ) ) , Bytes ( " base16 " , " 00 " ) ) )
def sendTransfer ( ) :
aid = ScratchVar ( )
amount = ScratchVar ( )
d = ScratchVar ( )
p = ScratchVar ( )
asset = ScratchVar ( )
aaddr = ScratchVar ( )
Address = ScratchVar ( )
FromChain = ScratchVar ( )
zb = ScratchVar ( )
factor = ScratchVar ( )
fee = ScratchVar ( )
return Seq ( [
mfee . store ( getMessageFee ( ) ) ,
zb . store ( BytesZero ( Int ( 32 ) ) ) ,
aid . store ( Btoi ( Txn . application_args [ 1 ] ) ) ,
# what should we pass as a fee...
fee . store ( Btoi ( Txn . application_args [ 5 ] ) ) ,
checkFeePmt ( Int ( 2 ) ) ,
tidx . store ( Txn . group_index ( ) - Int ( 1 ) ) ,
If ( aid . load ( ) == Int ( 0 ) ,
Seq ( [
MagicAssert ( And (
# The previous txn is the asset transfer itself
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . Payment ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
Gtxn [ tidx . load ( ) ] . receiver ( ) == Txn . accounts [ 2 ] ,
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] ) ,
amount . store ( Gtxn [ tidx . load ( ) ] . amount ( ) ) ,
2022-06-20 08:46:49 -07:00
# fee cannot exceed amount
MagicAssert ( fee . load ( ) < = amount . load ( ) ) ,
2022-04-29 12:53:48 -07:00
] ) ,
Seq ( [
MagicAssert ( And (
# The previous txn is the asset transfer itself
Gtxn [ tidx . load ( ) ] . type_enum ( ) == TxnType . AssetTransfer ,
Gtxn [ tidx . load ( ) ] . sender ( ) == Txn . sender ( ) ,
Gtxn [ tidx . load ( ) ] . xfer_asset ( ) == aid . load ( ) ,
Gtxn [ tidx . load ( ) ] . asset_receiver ( ) == Txn . accounts [ 2 ] ,
) ) ,
assert_common_checks ( Gtxn [ tidx . load ( ) ] ) ,
amount . store ( Gtxn [ tidx . load ( ) ] . asset_amount ( ) ) ,
2022-06-20 08:46:49 -07:00
# fee cannot exceed amount
2022-04-29 12:53:48 -07:00
MagicAssert ( fee . load ( ) < = amount . load ( ) ) ,
factor . store ( getFactor ( Btoi ( extract_decimal ( aid . load ( ) ) ) ) ) ,
If ( factor . load ( ) != Int ( 1 ) ,
Seq ( [
amount . store ( amount . load ( ) / factor . load ( ) ) ,
fee . store ( fee . load ( ) / factor . load ( ) ) ,
] )
) , # If(factor.load() != Int(1),
] ) ,
) ,
# If it is nothing but dust lets just abort the whole transaction and save
MagicAssert ( And ( amount . load ( ) > Int ( 0 ) , fee . load ( ) > = Int ( 0 ) ) ) ,
If ( aid . load ( ) != Int ( 0 ) ,
aaddr . store ( auth_addr ( extract_creator ( aid . load ( ) ) ) ) ,
aaddr . store ( Bytes ( " " ) ) ) ,
# Is the authorizing signature of the creator of the asset the address of the token_bridge app itself?
If ( aaddr . load ( ) == Global . current_application_address ( ) ,
Seq ( [
asset . store ( blob . read ( Int ( 2 ) , Int ( 0 ) , Int ( 8 ) ) ) ,
# This the correct asset?
MagicAssert ( Txn . application_args [ 1 ] == asset . load ( ) ) ,
# Pull the address and chain out of the original vaa
Address . store ( blob . read ( Int ( 2 ) , Int ( 60 ) , Int ( 92 ) ) ) ,
FromChain . store ( blob . read ( Int ( 2 ) , Int ( 92 ) , Int ( 94 ) ) ) ,
# This the correct page given the chain and the address
MagicAssert ( Txn . accounts [ 2 ] == get_sig_address ( Btoi ( FromChain . load ( ) ) , Address . load ( ) ) ) ,
] ) ,
Seq ( [
MagicAssert ( Txn . accounts [ 2 ] == get_sig_address ( aid . load ( ) , Bytes ( " native " ) ) ) ,
FromChain . store ( Bytes ( " base16 " , " 0008 " ) ) ,
Address . store ( Txn . application_args [ 1 ] ) ,
] )
) ,
# Correct address len?
MagicAssert ( And (
Len ( Address . load ( ) ) < = Int ( 32 ) ,
Len ( FromChain . load ( ) ) == Int ( 2 ) ,
Len ( Txn . application_args [ 3 ] ) < = Int ( 32 )
) ) ,
p . store ( Concat (
If ( Txn . application_args . length ( ) == Int ( 6 ) ,
Bytes ( " base16 " , " 01 " ) ,
Bytes ( " base16 " , " 03 " ) ) ,
Extract ( zb . load ( ) , Int ( 0 ) , Int ( 24 ) ) ,
Itob ( amount . load ( ) ) , # 8 bytes
Extract ( zb . load ( ) , Int ( 0 ) , Int ( 32 ) - Len ( Address . load ( ) ) ) ,
Address . load ( ) ,
FromChain . load ( ) ,
Extract ( zb . load ( ) , Int ( 0 ) , Int ( 32 ) - Len ( Txn . application_args [ 3 ] ) ) ,
Txn . application_args [ 3 ] ,
Extract ( Txn . application_args [ 4 ] , Int ( 6 ) , Int ( 2 ) ) ,
2022-05-23 12:22:40 -07:00
If ( Txn . application_args . length ( ) == Int ( 7 ) , Concat ( Txn . sender ( ) , Txn . application_args [ 6 ] ) , Concat ( Extract ( zb . load ( ) , Int ( 0 ) , Int ( 24 ) ) , Itob ( fee . load ( ) ) ) )
2022-04-29 12:53:48 -07:00
) ) ,
# This one magic line should protect us from overruns/underruns and trickery..
If ( Txn . application_args . length ( ) == Int ( 7 ) ,
MagicAssert ( Len ( p . load ( ) ) == Int ( 133 ) + Len ( Txn . application_args [ 6 ] ) ) ,
MagicAssert ( Len ( p . load ( ) ) == Int ( 133 ) ) ) ,
InnerTxnBuilder . Begin ( ) ,
sendMfee ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . type_enum : TxnType . ApplicationCall ,
TxnField . application_id : App . globalGet ( Bytes ( " coreid " ) ) ,
TxnField . application_args : [ Bytes ( " publishMessage " ) , p . load ( ) , Itob ( Int ( 0 ) ) ] ,
TxnField . accounts : [ Txn . accounts [ 1 ] ] ,
TxnField . note : Bytes ( " publishMessage " ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
InnerTxnBuilder . Submit ( ) ,
Approve ( )
] )
def do_optin ( ) :
return Seq ( [
MagicAssert ( Txn . accounts [ 1 ] == get_sig_address ( Btoi ( Txn . application_args [ 1 ] ) , Bytes ( " native " ) ) ) ,
assert_common_checks ( Txn ) ,
InnerTxnBuilder . Begin ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . sender : Txn . accounts [ 1 ] ,
TxnField . type_enum : TxnType . AssetTransfer ,
TxnField . xfer_asset : Btoi ( Txn . application_args [ 1 ] ) ,
TxnField . asset_amount : Int ( 0 ) ,
TxnField . asset_receiver : Txn . accounts [ 1 ] ,
TxnField . fee : Int ( 0 ) ,
}
) ,
InnerTxnBuilder . Submit ( ) ,
Approve ( )
] )
# This is for attesting
def attestToken ( ) :
asset = ScratchVar ( )
p = ScratchVar ( )
zb = ScratchVar ( )
d = ScratchVar ( )
uname = ScratchVar ( )
name = ScratchVar ( )
aid = ScratchVar ( )
Address = ScratchVar ( )
FromChain = ScratchVar ( )
return Seq ( [
mfee . store ( getMessageFee ( ) ) ,
checkFeePmt ( Int ( 1 ) ) ,
aid . store ( Btoi ( Txn . application_args [ 1 ] ) ) ,
# Is the authorizing signature of the creator of the asset the address of the token_bridge app itself?
If ( If ( aid . load ( ) != Int ( 0 ) , auth_addr ( extract_creator ( aid . load ( ) ) ) == Global . current_application_address ( ) , Int ( 0 ) ) ,
Seq ( [
2022-06-20 08:46:49 -07:00
# Cannot attest a wormhole wrapped token
Reject ( )
2022-04-29 12:53:48 -07:00
] ) ,
Seq ( [
MagicAssert ( Txn . accounts [ 2 ] == get_sig_address ( aid . load ( ) , Bytes ( " native " ) ) ) ,
zb . store ( BytesZero ( Int ( 32 ) ) ) ,
aid . store ( Btoi ( Txn . application_args [ 1 ] ) ) ,
If ( aid . load ( ) == Int ( 0 ) ,
Seq ( [
d . store ( Bytes ( " base16 " , " 06 " ) ) ,
uname . store ( Bytes ( " ALGO " ) ) ,
name . store ( Bytes ( " ALGO " ) )
] ) ,
Seq ( [
d . store ( extract_decimal ( aid . load ( ) ) ) ,
If ( Btoi ( d . load ( ) ) > Int ( 8 ) , d . store ( Bytes ( " base16 " , " 08 " ) ) ) ,
uname . store ( extract_unit_name ( aid . load ( ) ) ) ,
name . store ( extract_name ( aid . load ( ) ) ) ,
] )
) ,
p . store (
Concat (
#PayloadID uint8 = 2
Bytes ( " base16 " , " 02 " ) ,
#TokenAddress [32]uint8
Extract ( zb . load ( ) , Int ( 0 ) , Int ( 24 ) ) ,
Itob ( aid . load ( ) ) ,
#TokenChain uint16
Bytes ( " base16 " , " 0008 " ) ,
#Decimals uint8
d . load ( ) ,
#Symbol [32]uint8
uname . load ( ) ,
Extract ( zb . load ( ) , Int ( 0 ) , Int ( 32 ) - Len ( uname . load ( ) ) ) ,
#Name [32]uint8
name . load ( ) ,
Extract ( zb . load ( ) , Int ( 0 ) , Int ( 32 ) - Len ( name . load ( ) ) ) ,
)
) ,
] )
) ,
MagicAssert ( Len ( p . load ( ) ) == Int ( 100 ) ) ,
InnerTxnBuilder . Begin ( ) ,
sendMfee ( ) ,
InnerTxnBuilder . SetFields (
{
TxnField . type_enum : TxnType . ApplicationCall ,
TxnField . application_id : App . globalGet ( Bytes ( " coreid " ) ) ,
TxnField . application_args : [ Bytes ( " publishMessage " ) , p . load ( ) , Itob ( Int ( 0 ) ) ] ,
TxnField . accounts : [ Txn . accounts [ 1 ] ] ,
TxnField . note : Bytes ( " publishMessage " ) ,
TxnField . fee : Int ( 0 ) ,
}
) ,
InnerTxnBuilder . Submit ( ) ,
Approve ( )
] )
@Subroutine ( TealType . none )
def checkForDuplicate ( ) :
off = ScratchVar ( )
emitter = ScratchVar ( )
sequence = ScratchVar ( )
b = ScratchVar ( )
byte_offset = ScratchVar ( )
return Seq (
# VM only is version 1
MagicAssert ( Btoi ( Extract ( Txn . application_args [ 1 ] , Int ( 0 ) , Int ( 1 ) ) ) == Int ( 1 ) ) ,
off . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , Int ( 5 ) , Int ( 1 ) ) ) * Int ( 66 ) + Int ( 14 ) ) , # The offset of the emitter
# emitter is chain/contract-address
emitter . store ( Extract ( Txn . application_args [ 1 ] , off . load ( ) , Int ( 34 ) ) ) ,
sequence . store ( Btoi ( Extract ( Txn . application_args [ 1 ] , off . load ( ) + Int ( 34 ) , Int ( 8 ) ) ) ) ,
# They passed us the correct account? In this case, byte_offset points at the whole block
byte_offset . store ( sequence . load ( ) / Int ( max_bits ) ) ,
MagicAssert ( Txn . accounts [ 1 ] == get_sig_address ( byte_offset . load ( ) , emitter . load ( ) ) ) ,
# Now, lets go grab the raw byte
byte_offset . store ( ( sequence . load ( ) / Int ( 8 ) ) % Int ( max_bytes ) ) ,
b . store ( blob . get_byte ( Int ( 1 ) , byte_offset . load ( ) ) ) ,
# I would hope we've never seen this packet before... throw an exception if we have
MagicAssert ( GetBit ( b . load ( ) , sequence . load ( ) % Int ( 8 ) ) == Int ( 0 ) ) ,
# Lets mark this bit so that we never see it again
blob . set_byte ( Int ( 1 ) , byte_offset . load ( ) , SetBit ( b . load ( ) , sequence . load ( ) % Int ( 8 ) , Int ( 1 ) ) )
)
def nop ( ) :
return Seq ( [ Approve ( ) ] )
router = Cond (
[ METHOD == Bytes ( " nop " ) , nop ( ) ] ,
[ METHOD == Bytes ( " receiveAttest " ) , receiveAttest ( ) ] ,
[ METHOD == Bytes ( " attestToken " ) , attestToken ( ) ] ,
[ METHOD == Bytes ( " completeTransfer " ) , completeTransfer ( ) ] ,
[ METHOD == Bytes ( " sendTransfer " ) , sendTransfer ( ) ] ,
[ METHOD == Bytes ( " optin " ) , do_optin ( ) ] ,
[ METHOD == Bytes ( " governance " ) , governance ( ) ]
)
on_create = Seq ( [
App . globalPut ( Bytes ( " coreid " ) , Btoi ( Txn . application_args [ 0 ] ) ) ,
App . globalPut ( Bytes ( " coreAddr " ) , Txn . application_args [ 1 ] ) ,
App . globalPut ( Bytes ( " validUpdateApproveHash " ) , Bytes ( " " ) ) ,
App . globalPut ( Bytes ( " validUpdateClearHash " ) , Bytes ( " base16 " , " 73be5fd7cd378289177bf4a7ca5433ab30d91b417381bba8bd704aff2dec424f " ) ) , # empty clear state program
Return ( Int ( 1 ) )
] )
def getOnUpdate ( ) :
if devMode :
return Seq ( [
Return ( Txn . sender ( ) == Global . creator_address ( ) ) ,
] )
else :
return Seq ( [
MagicAssert ( Sha512_256 ( Concat ( Bytes ( " Program " ) , Txn . approval_program ( ) ) ) == App . globalGet ( Bytes ( " validUpdateApproveHash " ) ) ) ,
MagicAssert ( Sha512_256 ( Concat ( Bytes ( " Program " ) , Txn . clear_state_program ( ) ) ) == App . globalGet ( Bytes ( " validUpdateClearHash " ) ) ) ,
Return ( Int ( 1 ) )
] )
on_update = getOnUpdate ( )
@Subroutine ( TealType . uint64 )
def optin ( ) :
# Alias for readability
2022-06-23 12:43:21 -07:00
algo_seed = Gtxn [ Txn . group_index ( ) - Int ( 1 ) ]
optin = Txn
2022-04-29 12:53:48 -07:00
well_formed_optin = And (
# Check that we're paying it
algo_seed . type_enum ( ) == TxnType . Payment ,
algo_seed . amount ( ) == Int ( seed_amt ) ,
# Check that its an opt in to us
optin . type_enum ( ) == TxnType . ApplicationCall ,
optin . on_completion ( ) == OnComplete . OptIn
)
return Seq (
# Make sure its a valid optin
MagicAssert ( well_formed_optin ) ,
# Init by writing to the full space available for the sender (Int(0))
blob . zero ( Int ( 0 ) ) ,
# we gucci
Int ( 1 )
)
on_optin = Seq ( [
Return ( optin ( ) )
] )
return Cond (
[ Txn . application_id ( ) == Int ( 0 ) , on_create ] ,
[ Txn . on_completion ( ) == OnComplete . UpdateApplication , on_update ] ,
[ Txn . on_completion ( ) == OnComplete . DeleteApplication , on_delete ] ,
[ Txn . on_completion ( ) == OnComplete . OptIn , on_optin ] ,
[ Txn . on_completion ( ) == OnComplete . NoOp , router ]
)
def get_token_bridge ( genTeal , approve_name , clear_name , client : AlgodClient , seed_amt : int , tmpl_sig : TmplSig , devMode : bool ) - > Tuple [ bytes , bytes ] :
if not devMode :
client = AlgodClient ( " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " , " https://testnet-api.algonode.cloud " )
2022-05-05 06:23:42 -07:00
APPROVAL_PROGRAM = fullyCompileContract ( genTeal , client , approve_token_bridge ( seed_amt , tmpl_sig , devMode ) , approve_name , devMode )
CLEAR_STATE_PROGRAM = fullyCompileContract ( genTeal , client , clear_token_bridge ( ) , clear_name , devMode )
2022-04-29 12:53:48 -07:00
return APPROVAL_PROGRAM , CLEAR_STATE_PROGRAM