def takeOwnership(toAcct, tokenID): """ transfer the approved tokenId token to toAcct the invoker can be the owner or the approved account toAcct can be any address :param toAcct: the account that will be assigned as the new owner of tokenId :param tokenID: the tokenId token will be assigned to toAcct :return: False or True """ if len(toAcct) != 20: raise Exception("toAcct illegal!") tokenOwner = ownerOf(tokenID) if not tokenOwner: return False approveKey = concatkey(APPROVE_PREFIX, tokenID) approvedAcct = Get(ctx, approveKey) if CheckWitness(tokenOwner) != True and CheckWitness(approvedAcct) != True: return False Delete(ctx, approveKey) ownerKey = concatkey(OWNER_OF_TOKEN_PREFIX, tokenID) Put(ctx, ownerKey, toAcct) fromBalance = balanceOf(tokenOwner) toBalance = balanceOf(toAcct) # to avoid overflow if fromBalance >= 1 and toBalance < toBalance + 1: Put(ctx, concatkey(OWNER_BALANCE_PREFIX, tokenOwner), fromBalance - 1) Put(ctx, concatkey(OWNER_BALANCE_PREFIX, toAcct), toBalance + 1) Notify(['transfer', tokenOwner, toAcct, tokenID]) return True
def _onlyCLevel(): isCEO = CheckWitness(CEOAddress) isCTO = None isCOO = None CTOAddress = getCTO() if len(CTOAddress) == 20: isCTO = CheckWitness(CTOAddress) COOAddress = getCOO() if len(COOAddress) == 20: isCOO = CheckWitness(COOAddress) return isCEO or isCTO or isCOO
def setLawEnforcementRole(newEnforceRole): """ Set Enforment role address. :param newEnforceRole: new enforcement role acccount. :return: """ assert (isAddress(newEnforceRole)) assert (CheckWitness(getEnforcementRole() or CheckWitness(getOwner()))) Put(ctx, ENFORCEMENT_ROLE_KEY, newEnforceRole) return True
def lock(fromAssetHash, fromAddress, toChainId, toAddress, amount): """ Decrease token supply from deducter address. :param amount: decreased token amount. :return: """ assert (amount >= 0) assert (CheckWitness(fromAddress)) assert (len(toAddress) != 0) # transfer asset from fromAddress to lock proxy contract assert (_transferToContract(fromAssetHash, fromAddress, amount)) # construct args for proxy contract in target chain toAssetHash = getAssetHash(fromAssetHash, toChainId) # make sure the toAssetHash is not empty assert (len(toAssetHash) != 0) argsList = [toAssetHash, toAddress, amount] # invoke the native cross chain manager contract to make transaction to target chain inputArgs = _serialzieArgs(argsList) toProxyHash = getProxyHash(toChainId) # make sure the toProxyHash is not empty assert (len(toProxyHash) != 0) param = state(toChainId, toProxyHash, "unlock", inputArgs) assert (Invoke(0, CROSS_CHAIN_CONTRACT_ADDRESS, "createCrossChainTx", param)) LockEvent(fromAssetHash, fromAddress, toChainId, toAssetHash, toAddress, amount) return True
def bindAssetHash(fromAssetHash, toChainId, toAssetHash): assert (CheckWitness(Get(GetContext(), OPERATOR_PREFIX))) assert (_addFromAssetHash(fromAssetHash)) Put(GetContext(), concat(ASSET_HASH, concat(fromAssetHash, toChainId)), toAssetHash) curBalance = getBalanceFor(fromAssetHash) Notify(["bindAssetHash", fromAssetHash, toChainId, toAssetHash, curBalance]) return True
def takeOwnership(toAcct, tokenID): """ take the approved token :param toAcct: spender :param tokenID: this tokenID should be approved by its owner to toAcct :return: False or True """ if CheckWitness(toAcct) == False: return False tokenOwner = ownerOf(tokenID) if not tokenOwner: return False approveKey = concatkey(APPROVE_PREFIX, tokenID) approvedAcct = Get(ctx, concatkey(APPROVE_PREFIX, tokenID)) if approvedAcct != toAcct: return False Delete(ctx, approveKey) ownerKey = concatkey(OWNER_OF_TOKEN_PREFIX, tokenID) Put(ctx, ownerKey, toAcct) fromBalance = balanceOf(tokenOwner) toBalance = balanceOf(toAcct) # to avoid overflow if fromBalance > 1 and toBalance < toBalance + 1: Put(ctx, concatkey(OWNER_BALANCE_PREFIX, tokenOwner), fromBalance - 1) Put(ctx, concatkey(OWNER_BALANCE_PREFIX, toAcct), toBalance + 1) Notify(['transfer', tokenOwner, toAcct, tokenID]) return True
def transfer(toAcct, tokenID): """ transfer the token with tokenID to the toAcct :param toAcct: to account address :param tokenID: the unique token's ID, type should be ByteArray :return: False means failure, True means success. """ tokenOwner = ownerOf(tokenID) if CheckWitness(tokenOwner) == False: return False if len(toAcct) != 20: raise Exception('address length error!') ownerKey = concatkey(OWNER_OF_TOKEN_PREFIX, tokenID) fromAcct = Get(ctx, ownerKey) balanceKey = concatkey(OWNER_BALANCE_PREFIX, fromAcct) fromBalance = Get(ctx, balanceKey) if fromBalance >= 1: # decrease fromAccount token balance Put(ctx, balanceKey, fromBalance - 1) else: raise Exception('fromBalance error') # set the owner of tokenID to toAcct Put(ctx, ownerKey, toAcct) # increase toAccount token balance balanceKey = concatkey(OWNER_BALANCE_PREFIX, toAcct) Put(ctx, balanceKey, balanceOf(toAcct) + 1) Notify(['transfer', fromAcct, toAcct, tokenID]) return True
def upgrade(code): """ upgrade current smart contract to new smart contract. :param code:new smart contract avm code. :return: True or raise exception. """ owner = getOwner() assert (CheckWitness(owner)) ongBalance = Invoke(0, ONG_ADDRESS, 'balanceOf', state(CONTRACT_ADDRESS)) res = Invoke(0, ONG_ADDRESS, "transfer", [state(CONTRACT_ADDRESS, owner, ongBalance)]) if res != b'\x01': assert (False) ontBalance = Invoke(0, ONT_ADDRESS, 'balanceOf', state(CONTRACT_ADDRESS)) res = Invoke(0, ONT_ADDRESS, "transfer", [state(CONTRACT_ADDRESS, owner, ontBalance)]) if res != b'\x01': assert (False) # upgrade smart contract res = Migrate(code, "", "", "", "", "", "") if not res: assert (False) Notify(["upgrade smart contract"]) return True
def lock(toChainId, fromAddress, toAddress, amount): """ Decrease token supply from deducter address. :param amount: decreased token amount. :return: """ fee = 0 assert (amount >= 0) assert (CheckWitness(fromAddress)) assert (not isPaused()) # eth address format:0x673dfa9caf9145fdbef98e9d9874f36e63d8a5b4,length is 42 assert (len(toAddress) != 0) Put(ctx, concat(BALANCE_KEY, fromAddress), Sub(balanceOf(fromAddress), amount)) Put(ctx, TOTAL_SUPPLY_KEY, Sub(totalSupply(), amount)) # construct args for proxy contract in target chain toAssetHash = getAssetHash(toChainId) argsList = [toAddress, amount] input_bytes = _serialzieArgs(argsList) param = state(toChainId, toAssetHash, "unlock", input_bytes) assert (Invoke(0, CROSS_CHAIN_CONTRACT_ADDRESS, "createCrossChainTx", param)) LockEvent(toChainId, fromAddress, toAddress, amount) return True
def transferOwnership(newOwner): oldOwner = getOwner() assert (CheckWitness(oldOwner)) assert (len(newOwner) == 20 and newOwner != ZERO_ADDRESS) Put(GetContext(), OWNER_KEY, newOwner) TransferOwnershipEvent(oldOwner, newOwner) return True
def add_ong(address, amount): byte_address = Base58ToAddress(address) assert (CheckWitness(byte_address)) if len(byte_address) != 20: Notify(['Invalid address']) return False if amount < 0: Notify(['Negative amount']) return False supply = Get(ctx, ONGKEY) if supply < amount: Notify(['Not enough ONG in supply']) return False else: from_acct = contract_address to_acct = byte_address supply -= amount Put(ctx, ONGKEY, supply) Notify(['ONG supply decreased by', amount]) params = state(from_acct, to_acct, amount) return Invoke(1, contract_address_ONG, 'transfer', [params])
def transferONT(fromacct, toacct, amount): """ transfer ONT :param fromacct: :param toacct: :param amount: :return: """ if CheckWitness(fromacct): param = makeState(fromacct, toacct, amount) res = Invoke(0, contractAddress, 'transfer', [fromacct, toacct, amount]) Notify(["11111", res]) if res and res == b'\x01': Notify('transfer succeed') return True else: Notify('transfer failed') return False else: Notify('checkWitness failed') return False
def create_user(address, username, bio): # only the address can invoke the method assert (CheckWitness(address)) # check if username has been created. if not, initialize it. Otherwise, rollback the transaction assert (not user_exist(address)) # check if user has been created. if not, initialize it. Otherwise, rollback the transaction assert (not get_address_by_username(username)) # mark username as being used one Put(ctx, concatkey(username, UN_EXIST_PREFIX), address) if len(bio) > 100: Notify(['Bio length exceeds 100 characters']) # create profile info list profile = [username, bio] profile_info = Serialize(profile) Put(ctx, concatkey(address, PI_PREFIX), profile_info) # update reputation of address Put(ctx, concatkey(address, REPKEY_PREFIX), (100 + 100000000) * AES_FACTOR) # distribute a certain amount of token to the newly registered user token_amount = 100 * AES_FACTOR assert (withdraw(address, token_amount)) Notify(["userCreated", address, username, bio]) return True
def transfer(from_acct, to_acct, amount): """ Transfer amount of tokens from from_acct to to_acct :param from_acct: the account from which the amount of tokens will be transferred :param to_acct: the account to which the amount of tokens will be transferred :param amount: the amount of the tokens to be transferred, >= 0 :return: True means success, False or raising exception means failure. """ if len(to_acct) != 20 or len(from_acct) != 20: raise Exception("Address length error") if CheckWitness(from_acct) == False: raise Exception("Check Witness fail") fromKey = concat(BALANCE_PREFIX, from_acct) fromBalance = Get(ctx, fromKey) if amount > fromBalance: raise Exception("amount > fromBalance") if amount == fromBalance: Delete(ctx, fromKey) else: Put(ctx, fromKey, fromBalance - amount) toKey = concat(BALANCE_PREFIX, to_acct) toBalance = Get(ctx, toKey) Put(ctx, toKey, toBalance + amount) # Notify(["transfer", AddressToBase58(from_acct), AddressToBase58(to_acct), amount]) # TransferEvent(AddressToBase58(from_acct), AddressToBase58(to_acct), amount) TransferEvent(from_acct, to_acct, amount)
def RequireWitness(address): ''' Raises an exception if the given address is not a witness. :param address: The address to check. ''' Require(CheckWitness(address), "Address is not witness")
def transfer(from_acct,to_acct,amount): """ Transfer amount of tokens from from_acct to to_acct :param from_acct: the account from which the amount of tokens will be transferred :param to_acct: the account to which the amount of tokens will be transferred :param amount: the amount of the tokens to be transferred, >= 0 :return: True means success, False or raising exception means failure. """ require(len(to_acct) == 20 and len(from_acct) == 20, "address length error") require(CheckWitness(from_acct) == True, "Invalid invoker") require(amount > 0, "Invalid Amount") whenNotPaused() requireNotFreeze(from_acct) requireNotFreeze(to_acct) fromKey = concat(BALANCE_PREFIX,from_acct) fromBalance = Get(ctx,fromKey) require(amount <= fromBalance, "Not enough balance") if amount == fromBalance: Delete(ctx,fromKey) else: Put(ctx,fromKey,fromBalance - amount) toKey = concat(BALANCE_PREFIX,to_acct) toBalance = Get(ctx,toKey) Put(ctx,toKey,toBalance + amount) # Notify(["transfer", AddressToBase58(from_acct), AddressToBase58(to_acct), amount]) # TransferEvent(AddressToBase58(from_acct), AddressToBase58(to_acct), amount) TransferEvent(from_acct, to_acct, amount) return True
def approve(owner, spender, tokenId, amount): """ approve amount of the tokenId token to toAcct address, it can overwrite older approved amount :param owner: :param spender: :param tokenId: :param amount: :return: """ assert (_whenNotPaused()) # make sure the invoker is the owner address assert (CheckWitness(owner)) # make sure the address is legal assert (len(spender) == 20) assert (_tokenExist(tokenId)) ownerBalance = balanceOf(owner, tokenId) # you can use "if" to notify the corresponding message, or use assert to raise exception assert (ownerBalance >= amount) assert (amount > 0) key = _concatkey(_concatkey(_concatkey(APPROVE_PREFIX, tokenId), owner), spender) Put(GetContext(), key, amount) ApprovalEvent(owner, spender, tokenId, amount) return True
def transferFrom(spender, from_acct, to_acct, amount): if not CheckWitness(spender): return False Require(amount > 0) fromKey = concat(BALANCE_PREFIX, from_acct) fromBalance = Get(ctx, fromKey) if amount > fromBalance: return False approveKey = concat(concat(APPROVE_PREFIX, from_acct), spender) approvedAmount = Get(ctx, approveKey) if amount > approvedAmount: return False toKey = concat(BALANCE_PREFIX, to_acct) toBalance = Get(ctx, toKey) if amount == approvedAmount: Delete(ctx, approveKey) Put(ctx, fromKey, fromBalance - amount) else: Put(ctx, approveKey, approvedAmount - amount) Put(ctx, fromKey, fromBalance - amount) Put(ctx, toKey, toBalance + amount) TransferEvent(from_acct, to_acct, amount) return True
def transfer(from_acct, to_acct, amount): if not CheckWitness(from_acct): return False Require(amount > 0) fromKey = concat(BALANCE_PREFIX, from_acct) fromBalance = Get(ctx, fromKey) if amount > fromBalance: return False if amount == fromBalance: Delete(ctx, fromKey) else: Put(ctx, fromKey, fromBalance - amount) toKey = concat(BALANCE_PREFIX, to_acct) toBalance = Get(ctx, toKey) """ BALANCE_PREFIX is Substring of APPROVE_PREFIX The "tokey" can be _BALANCE_APPROVE... """ #Data-Injection-Attack Put(ctx, toKey, toBalance + amount) TransferEvent(from_acct, to_acct, amount) return True
def subtract_ong(address, amount): byte_address = Base58ToAddress(address) assert (CheckWitness(byte_address)) if len(byte_address) != 20: Notify(['Invalid address']) return False if amount < 0: Notify(['Negative amount']) return False param = state(byte_address) if Invoke(0, contract_address_ONG, 'balanceOf', param) < amount: Notify(['Not enough ONG in wallet']) return False else: from_acct = byte_address to_acct = contract_address supply = Get(ctx, ONGKEY) supply += amount Put(ctx, ONGKEY, supply) Notify(['ONG supply increased by', amount]) params = state(from_acct, to_acct, amount) return Invoke(1, contract_address_ONG, 'transfer', [params])
def migrateContract(code, needStorage, name, version, author, email, description): assert (CheckWitness(adminAddress)) res = Migrate(code, needStorage, name, version, author, email, description) assert (res) Notify(["migrateContract", adminAddress, GetTime()]) return True
def subtract_bank(address, amount): byte_address = Base58ToAddress(address) assert (CheckWitness(byte_address)) if len(byte_address) != 20: Notify(['Invalid address']) return False if amount < 0: Notify(['Negative amount']) return False if RepContract('balanceOf', [byte_address]) < amount: Notify(['Not enough AES in wallet']) return False else: from_acct = byte_address to_acct = contract_address supply = Get(ctx, AESKEY) supply += amount Put(ctx, AESKEY, supply) Notify(['AES supply increased by', amount]) params = [from_acct, to_acct, amount] return RepContract('transfer', params)
def transfer(from_acct, to_acct, amount): """ Transfer amount of tokens from from_acct to to_acct :param from_acct: the account from which the amount of tokens will be transferred :param to_acct: the account to which the amount of tokens will be transferred :param amount: the amount of the tokens to be transferred, >= 0 :return: True means success, False or raising exception means failure. """ assert (not isPaused()) assert (amount > 0) assert (isAddress(to_acct)) assert (CheckWitness(from_acct)) fromKey = concat(BALANCE_KEY, from_acct) fromBalance = balanceOf(from_acct) if amount > fromBalance: return False if amount == fromBalance: Delete(ctx, fromKey) else: Put(ctx, fromKey, Sub(fromBalance, amount)) toKey = concat(BALANCE_KEY, to_acct) toBalance = balanceOf(to_acct) Put(ctx, toKey, Add(toBalance, amount)) TransferEvent(from_acct, to_acct, amount) return True
def transfer(from_acct, to_acct, amount): """ Transfer amount of tokens from from_acct to to_acct :param from_acct: the account from which the amount of tokens will be transferred :param to_acct: the account to which the amount of tokens will be transferred :param amount: the amount of the tokens to be transferred, >= 0 :return: True means success, False or raising exception means failure. """ assert (len(to_acct) == 20) assert (len(from_acct) == 20) assert (CheckWitness(from_acct)) assert (amount > 0) fromKey = concat(BALANCE_PREFIX, from_acct) fromBalance = Get(ctx, fromKey) assert (fromBalance >= amount) if amount == fromBalance: Delete(ctx, fromKey) else: Put(ctx, fromKey, fromBalance - amount) toKey = concat(BALANCE_PREFIX, to_acct) toBalance = Get(ctx, toKey) Put(ctx, toKey, toBalance + amount) TransferEvent(from_acct, to_acct, amount) return True
def transfer(from_acct, to_acct, amount): """ Transfer amount of tokens from from_acct to to_acct :param from_acct: the account from which the amount of tokens will be transferred :param to_acct: the account to which the amount of tokens will be transferred :param amount: the amount of the tokens to be transferred, >= 0 :return: True means success, False or raising exception means failure. """ if len(to_acct) != 20 or len(from_acct) != 20: raise Exception("address length error") if CheckWitness(from_acct) == False or amount < 0: return False fromKey = concat(BALANCE_PREFIX, from_acct) fromBalance = Get(ctx,fromKey) if amount > fromBalance: return False if amount == fromBalance: Delete(ctx,fromKey) else: Put(ctx,fromKey,Sub(fromBalance, amount)) toKey = concat(BALANCE_PREFIX, to_acct) toBalance = Get(ctx, toKey) Put(ctx,toKey,Add(toBalance, amount)) TransferEvent(from_acct, to_acct, amount) return True
def transferFrom(spender, from_acct, to_acct, amount): """ spender spends amount of tokens on the behalf of from_acct, spender makes a transaction of amount of tokens from from_acct to to_acct :param spender: :param from_acct: :param to_acct: :param amount: :return: """ assert (len(spender) == 20 and len(from_acct) == 20 and len(to_acct) == 20) assert (CheckWitness(spender)) fromKey = concat(BALANCE_PREFIX, from_acct) fromBalance = Get(GetContext(), fromKey) assert (amount <= fromBalance and amount >= 0) approveKey = concat(concat(APPROVE_PREFIX, from_acct), spender) approvedAmount = Get(GetContext(), approveKey) toKey = concat(BALANCE_PREFIX, to_acct) assert (amount <= approvedAmount) if amount == approvedAmount: Delete(GetContext(), approveKey) Put(GetContext(), fromKey, fromBalance - amount) else: Put(GetContext(), approveKey, approvedAmount - amount) Put(GetContext(), fromKey, fromBalance - amount) toBalance = Get(GetContext(), toKey) Put(GetContext(), toKey, toBalance + amount) TransferEvent(from_acct, to_acct, amount) return True
def transferFrom(spender, from_acct, to_acct, amount): """ spender spends amount of tokens on the behalf of from_acct, spender makes a transaction of amount of tokens from from_acct to to_acct :param spender: :param from_acct: :param to_acct: :param amount: :return: """ assert (amount > 0) assert (isAddress(spender) and isAddress(from_acct) and isAddress(to_acct)) assert (CheckWitness(spender)) fromKey = concat(BALANCE_PREFIX, from_acct) fromBalance = balanceOf(from_acct) assert (fromBalance >= amount) approveKey = concat(concat(APPROVE_PREFIX, from_acct), spender) approvedAmount = Get(ctx, approveKey) if amount > approvedAmount: return False elif amount == approvedAmount: Delete(ctx, approveKey) Put(ctx, fromKey, Sub(fromBalance, amount)) else: Put(ctx, approveKey, Sub(approvedAmount, amount)) Put(ctx, fromKey, Sub(fromBalance, amount)) toBalance = balanceOf(to_acct) Put(ctx, concat(BALANCE_PREFIX, to_acct), Add(toBalance, amount)) TransferFromEvent(spender, from_acct, to_acct, amount) return True
def upgrade(code): """ migrate data to new contract, transfer asset to admin address :param code: :return: """ assert CheckWitness(ADMIN) # transfer ont ont_balance = Invoke(VERSION, ONT_ADDRESS, "balanceOf", state(CONTRACT_ADDRESS)) ont_response = Invoke(VERSION, ONT_ADDRESS, "transfer", [state(CONTRACT_ADDRESS, ADMIN, ont_balance)]) if ont_response != INVOKE_SUCCESS: raise Exception("contract upgrade - transfer ont failed") # transfer ong ong_balance = Invoke(VERSION, ONG_ADDRESS, "balanceOf", state(CONTRACT_ADDRESS)) ong_response = Invoke(VERSION, ONG_ADDRESS, "transfer", [state(CONTRACT_ADDRESS, ADMIN, ong_balance)]) if ong_response != INVOKE_SUCCESS: raise Exception("contract upgrade - transfer ong failed") # migrate avm migrate_response = Migrate(code, "", "", "", "", "", "") if not migrate_response: raise Exception("contract upgrade - migrate avm failed") Notify(["upgrade", "success"]) return True
def RequireWitness(witness): """ Checks the tx sender is equal to the witness. If not satisfying, revert the transaction. """ Require(CheckWitness(witness)) return True
def AddToken(symbol, hash): """ :param symbol:token symbol, like "ONT", "ONG" :param hash: token script hash,such as ONT,ONG or other token hash, if success, this token can be exchanged on the exchange. :return:True or False """ require(CheckWitness(Admin), "not admin") require(validateAddress(hash), "invalid contract hash") if Get(ctx, concatKey(TOKEN_SYMBOL_PREFIX, symbol)): return False if Get(ctx, concatKey(TOKEN_HASH_PREFIX, hash)): return False supportToken = Get(ctx, SUPPORTED_TOKEN) if not supportToken: tokenMap = {symbol: hash} else: tokenMap = Deserialize(supportToken) tokenMap[symbol] = hash Put(ctx, concatKey(TOKEN_SYMBOL_PREFIX, symbol), symbol) Put(ctx, concatKey(TOKEN_HASH_PREFIX, hash), hash) Put(ctx, SUPPORTED_TOKEN, Serialize(tokenMap)) return True