0% found this document useful (0 votes)
34 views11 pages

Smart Contract Security Audit report-oETH

Uploaded by

KevinHoston
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views11 pages

Smart Contract Security Audit report-oETH

Uploaded by

KevinHoston
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Smart contract security

audit report
Audit Number:202009131830

Smart Contract Name:

oETH.py

Smart Contract Hash:

a2f89e531e55636d4af1cd044237d2fd5a616c72

Smart Contract Address Link:

https://github.com/polynetwork/ont-contracts/blob/master/contracts/core/assets/oETH.py

Commit Hash:

027fbdf5f4ed46195401ed34264b1a93b128dba2

Start Date:2020.09.12

Completion Date:2020.09.13

Overall Result:Pass

Audit Team: Beosin (Chengdu LianAn) Technology Co. Ltd.

Audit Categories and Results:

No. Categories Subitems Results

OEP4 Token Standards Pass

Operator Security Audit Pass

Dictionary Use Security Audit Pass

Redundant Code Pass

Slice Security Audit Pass

1 Coding Conventions Module Audit Pass

Subscript Type Audit Pass

The Assert Audit Pass

Overriding Variables Pass

Gas Consumption Pass

Division By Zero Audit Pass

2 Function Call Audit Authorization of Function Call Pass


Returned Value Security Pass
RegisterAppCall & DynamicAppCall
Pass
Security Audit
Integer Overflow/Underflow Pass

Reentrancy Pass

Transaction-Ordering Dependence Pass


Pseudo-random Number Generator
Pass
(PRNG)
3 Common Vulnerability Audit Array subscript out-of-bounds audit Pass

DoS (Denial of Service) Pass

Token Vesting Implementation Missing

Data Injection Attack Audit Pass

event security Pass

Super Account Authority Audit Pass

4 Business Security Business Logics Pass

Business Implementations Pass


Note: Audit results and suggestions in code comments

Disclaimer: This audit is only applied to the type of auditing specified in this report and the scope of given in
the results table. Other unknown security vulnerabilities are beyond auditing responsibility. Beosin (Chengdu
LianAn) Technology only issues this report based on the attacks or vulnerabilities that already existed or
occurred before the issuance of this report. For the emergence of new attacks or vulnerabilities that exist or
occur in the future, Beosin (Chengdu LianAn) Technology lacks the capability to judge its possible impact on
the security status of smart contracts, thus taking no responsibility for them. The security audit analysis and
other contents of this report are based solely on the documents and materials that the contract provider has
provided to Beosin (Chengdu LianAn) Technology before the issuance of this report, and the contract
provider warrants that there are no missing, tampered, deleted; if the documents and materials provided by the
contract provider are missing, tampered, deleted, concealed or reflected in a situation that is inconsistent with
the actual situation, or if the documents and materials provided are changed after the issuance of this report,
Beosin (Chengdu LianAn) Technology assumes no responsibility for the resulting loss or adverse effects. The
audit report issued by Beosin (Chengdu LianAn) Technology is based on the documents and materials
provided by the contract provider, and relies on the technology currently possessed by Beosin (Chengdu
LianAn). Due to the technical limitations of any organization, this report conducted by Beosin (Chengdu
LianAn) still has the possibility that the entire risk cannot be completely detected. Beosin (Chengdu LianAn)
disclaims any liability for the resulting losses.

The final interpretation of this statement belongs to Beosin (Chengdu LianAn).


Audit Results Explained:

Beosin (Chengdu LianAn) Technology has used several methods including Formal Verification, Static
Analysis, Typical Case Testing and Manual Review to audit three major aspects of smart contracts oETH,
including Coding Standards, Security, and Business Logic. oETH contracts passed all audit items. The
overall result is Pass. The smart contract is able to function properly. Please find below the basic
information of the smart contract:

1、Basic Token Information

Token name oETH

Token symbol oETH

decimals 18

totalSupply 110 Billion (Mintable without the cap)

Token type OEP4

Table 1 - Basic Token Information

2、Token Vesting Information

Missing

3、Custom Function Description

 The delegateToProxy function

The contract implements the delegateToProxy function, which can mint tokens to the specified contract hash
(fb4a801e80f7d517a2d54510b1cdebeb4dee0334). The minting operation can only be performed by the
operator (ANXE3XovCwBH1ckQnPc6vKYiTwRXyrVToD).

Audited Source Code with Comments:

OntCversion = '2.0.0'
"""
oETH denotes the cross chain ETH asset on Ontology, which is same as Ether in Ethereum
"""
from ontology.interop.System.Storage import GetContext, Get, Put, Delete
from ontology.interop.System.Runtime import CheckWitness
from ontology.interop.System.Action import RegisterAction
from ontology.builtins import concat
from ontology.interop.Ontology.Runtime import Base58ToAddress

TransferEvent = RegisterAction("transfer", "from", "to", "amount") # Beosin (Chengdu LianAn) # Declare the e
vent 'TransferEvent'.
ApprovalEvent = RegisterAction("approval", "owner", "spender", "amount") # Beosin (Chengdu LianAn) # Decl
are the event 'ApprovalEvent'.
ctx = GetContext()

NAME = 'oETH' # Beosin (Chengdu LianAn) # The token name is 'oETH'.


SYMBOL = 'oETH' # Beosin (Chengdu LianAn) # The token symbol is 'oETH'.
DECIMALS = 18 # Beosin (Chengdu LianAn) # The token dedimals is 18.
FACTOR = 1000000000000000000
Operator = Base58ToAddress("ANXE3XovCwBH1ckQnPc6vKYiTwRXyrVToD") # Beosin (Chengdu LianAn)
# Set the Operator address to a specified address.
CROSS_CHAIN_CONTRACT_ADDRESS = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x09')
BALANCE_PREFIX = bytearray(b'\x01')
APPROVE_PREFIX = bytearray(b'\x02')
SUPPLY_KEY = 'TotalSupply'

PROXY_HASH_KEY = "Proxy"

def Main(operation, args):


"""
:param operation:
:param args:
:return:
"""
if operation == 'delegateToProxy':
return delegateToProxy(args[0], args[1])
if operation == 'name':
return name()
if operation == 'symbol':
return symbol()
if operation == 'decimals':
return decimals()
if operation == 'totalSupply':
return totalSupply()
if operation == 'balanceOf':
assert (len(args) == 1)
acct = args[0]
return balanceOf(acct)
if operation == 'transfer':
assert (len(args) == 3)
from_acct = args[0]
to_acct = args[1]
amount = args[2]
return transfer(from_acct, to_acct, amount)
if operation == 'transferMulti':
return transferMulti(args)
if operation == 'transferFrom':
assert (len(args) == 4)
spender = args[0]
from_acct = args[1]
to_acct = args[2]
amount = args[3]
return transferFrom(spender, from_acct, to_acct, amount)
if operation == 'approve':
assert (len(args) == 3)
owner = args[0]
spender = args[1]
amount = args[2]
return approve(owner, spender, amount)
if operation == 'allowance':
assert (len(args) == 2)
owner = args[0]
spender = args[1]
return allowance(owner, spender)

if operation == "getProxyHash":
return getProxyHash()
return False

# Beosin (Chengdu LianAn) # The function 'delegateToProxy' is defined to issue tokens to reserved address.
Note: this function can be called multiply.
def delegateToProxy(proxyReversedHash, amount):
"""
initialize the contract, put some important info into the storage in the blockchain
:return:
"""
assert (CheckWitness(Operator)) # Beosin (Chengdu LianAn) # Require that this function can be called onl
y by the Operator address.

storedProxy = getProxyHash()
if not storedProxy:
Put(ctx, PROXY_HASH_KEY, proxyReversedHash) # Beosin (Chengdu LianAn) # If the proxy reserved
address is not set, set the proxyReversedHash to the proxy reserved address.
else:
assert (proxyReversedHash == storedProxy) # Beosin (Chengdu LianAn) # Require that the recipient add
ress should only be the proxy reserved address.

Put(ctx, concat(BALANCE_PREFIX, proxyReversedHash), balanceOf(proxyReversedHash) + amount) # Beosi


n (Chengdu LianAn) # Update the token balance of the 'proxyReversedHash'.
Put(ctx, SUPPLY_KEY, totalSupply() + amount) # Beosin (Chengdu LianAn) # Update the total token suppl
y.
TransferEvent("", proxyReversedHash, amount) # Beosin (Chengdu LianAn) # Trigger the event 'TransferE
vent'.
return True

def name():
"""
:return: name of the token
"""
return NAME

def symbol():
"""
:return: symbol of the token
"""
return SYMBOL

def decimals():
"""
:return: the decimals of the token
"""
return DECIMALS

def totalSupply():
"""
:return: the total supply of the token
"""
return Get(ctx, SUPPLY_KEY)

def balanceOf(account):
"""
:param account:
:return: the token balance of account
"""
assert (len(account) == 20)
return Get(ctx, concat(BALANCE_PREFIX, account))

# Beosin (Chengdu LianAn) # The function 'transfer' is defined to transfer tokens.


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)) # Beosin (Chengdu LianAn) # Require that the address 'from_acct' shoul
d has corresponding permission.
assert (amount > 0) # Beosin (Chengdu LianAn) # Require that the transfer amount should be greater than
0.

fromKey = concat(BALANCE_PREFIX, from_acct)


fromBalance = Get(ctx, fromKey)
assert (fromBalance >= amount) # Beosin (Chengdu LianAn) # Balance check, require that the token balan
ce of 'from_acct' should not be less than the transfer amount.
# Beosin (Chengdu LianAn) # Update the token balance of 'from_acct'.
if amount == fromBalance:
Delete(ctx, fromKey)
else:
Put(ctx, fromKey, fromBalance - amount)
# Beosin (Chengdu LianAn) # Update the token balance of 'to_acct'.
toKey = concat(BALANCE_PREFIX, to_acct)
toBalance = Get(ctx, toKey)
Put(ctx, toKey, toBalance + amount)

TransferEvent(from_acct, to_acct, amount) # Beosin (Chengdu LianAn) # Trigger the event 'TransferEvent'
.

return True

# Beosin (Chengdu LianAn) # The function 'transferMulti' is defined to multiply transfer tokens.
def transferMulti(args):
"""
:param args: the parameter is an array, containing element like [from, to, amount]
:return: True means success, False or raising exception means failure.
"""
for p in args:
assert (len(p) == 3)
assert (transfer(p[0], p[1], p[2])) # Beosin (Chengdu LianAn) # Call the transfer function to transfer toke
ns and check its return value.

# return False is wrong since the previous transaction will be successful

return True

# Beosin (Chengdu LianAn) # The function 'approve' is defined to allow specified amount of tokens to a spec
ified address.
def approve(owner, spender, amount):
"""
owner allow spender to spend amount of token from owner account
Note here, the amount should be less than the balance of owner right now.
:param owner:
:param spender:
:param amount: amount>=0
:return: True means success, False or raising exception means failure.
"""
assert (len(owner) == 20)
assert (len(spender) == 20)
assert (CheckWitness(owner)) # Beosin (Chengdu LianAn) # Require that the address 'owner' should has c
orresponding permission.
assert (amount >= 0) # Beosin (Chengdu LianAn) # Require that the allowed amount should not be less tha
n 0.
assert (amount <= balanceOf(owner)) # Beosin (Chengdu LianAn) # Require that the approved amount sho
uld not exceed the holder’s balance.
# Beosin (Chengdu LianAn) # Set the approval amount between 2 addresses.
key = concat(concat(APPROVE_PREFIX, owner), spender)
Put(ctx, key, amount)
# Beosin (Chengdu LianAn) # Trigger the event 'ApprovalEvent'.
ApprovalEvent(owner, spender, amount)

return True

# Beosin (Chengdu LianAn) # The function 'transferFrom' is defined to delegate transfer tokens from addre
ss 'from_acct'.
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(to_acct) == 20)
assert (len(from_acct) == 20)
assert (len(spender) == 20)
assert (amount >= 0) # Beosin (Chengdu LianAn) # Require that the transfer amount should be greater tha
n 0.
assert (CheckWitness(spender)) # Beosin (Chengdu LianAn) # Require that the address 'spender' should ha
s corresponding permission.

fromKey = concat(BALANCE_PREFIX, from_acct)


fromBalance = Get(ctx, fromKey)

assert (fromBalance >= amount) # Beosin (Chengdu LianAn) # Require that the transfer amount should not
be less than the token balance of 'from_acct'.

approveKey = concat(concat(APPROVE_PREFIX, from_acct), spender)


approvedAmount = Get(ctx, approveKey)
toKey = concat(BALANCE_PREFIX, to_acct)

assert (approvedAmount >= amount) # Beosin (Chengdu LianAn) # Require that the approved amount shou
ld not be less than the transfer amount.
# Beosin (Chengdu LianAn) # Update the approved amount and the token balance of holder.
if amount == approvedAmount:
Delete(ctx, approveKey)
Put(ctx, fromKey, fromBalance - amount)
else:
Put(ctx, approveKey, approvedAmount - amount)
Put(ctx, fromKey, fromBalance - amount)
# Beosin (Chengdu LianAn) # Update the token balance of the 'to_acct'.
toBalance = Get(ctx, toKey)
Put(ctx, toKey, toBalance + amount)

TransferEvent(from_acct, to_acct, amount)

return True

def allowance(owner, spender):


"""
check how many token the spender is allowed to spend from owner account
:param owner: token owner
:param spender: token spender
:return: the allowed amount of tokens
"""
key = concat(concat(APPROVE_PREFIX, owner), spender)
return Get(ctx, key)

# Beosin (Chengdu LianAn) # The function 'getProxyHash' is defined to get the set proxy reserved address.
def getProxyHash():
return Get(ctx, PROXY_HASH_KEY)
Official Website
https://lianantech.com
E-mail
[email protected]
Twitter
https://twitter.com/Beosin_com

You might also like