题目
同上一题,只是这次的环境不是evm,而是cairo.
riddle-of-the-sphinx对应合约代码,贴在后面。
实现&分析
flag返回前提
还是一样的流程,flag返回前提变化:
async def checker(client: AccountClient, riddle_contract: Contract, player_address: int) -> bool:
solution = (await riddle_contract.functions["solution"].call()).solution
return to_bytes(solution).lstrip(b"\x00") == b"man"
关键返回内容转字符串后等于man。
思路
合约代码:
from starkware.cairo.common.cairo_builtins import HashBuiltin
@storage_var
func _solution() -> (res : felt):
end
@external
func solve{
syscall_ptr : felt*,
pedersen_ptr : HashBuiltin*,
range_check_ptr,
}(solution : felt):
_solution.write(solution)
return ()
end
@view
func solution{
syscall_ptr : felt*,
pedersen_ptr : HashBuiltin*,
range_check_ptr,
}() -> (solution : felt):
let (solution) = _solution.read()
return (solution)
end
调用solution方法查看_solution的值,调用solve方法写_solution,所以答案很明显了,调用solve传入值为man的数值即可。
题目内代码基本都有所有的调用方法,abi获取从remix编译后跳转可以查看。
调用值设定类似evm,不能用call,要用invoke,max_fee也要设置才行,具体实现见writeup。
writeup
from starknet_py.net.networks import *
from starknet_py.net.gateway_client import *
from starknet_py.net.http_client import *
from starknet_py.net import AccountClient,KeyPair
from starknet_py.contract import *
from starkware.python.utils import *
from starknet_py.net.full_node_client import FullNodeClient
from starknet_py.net import AccountClient
from starknet_py.cairo.felt import *
from starkware.crypto.signature.signature import private_to_stark_key
import threading,asyncio
from starkware.starknet.services.api.messages import StarknetMessageToL1, StarknetMessageToL2
from starkware.starknet.core.os.contract_address.contract_address import \
calculate_contract_address_from_hash
uuid = "xxxx"
url = "xxxx"
pkey = xxxx
contract = xxxx
ticket = "xxxx"
config1 = {"abi":
[
{
"name": "solve",
"type": "function",
"inputs": [
{
"name": "solution",
"type": "felt"
}
],
"outputs": []
},
{
"name": "solution",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "solution",
"type": "felt"
}
],
"stateMutability": "view"
}
]
}
async def getSolution():
client = GatewayClient(url, TESTNET)
pubkey = private_to_stark_key(pkey)
fullNodeClient = AccountClient(
client=client,
address=calculate_contract_address_from_hash(
salt=20,
class_hash=1803505466663265559571280894381905521939782500874858933595227108099796801620,
constructor_calldata=[pubkey],
deployer_address=0,
),
key_pair=KeyPair(
private_key=pkey, public_key=private_to_stark_key(pkey)
),
chain=StarknetChainId.TESTNET,
)
riddleContract = Contract(address=contract, abi=config1["abi"], client=fullNodeClient)
result = (await riddleContract.functions['solve'].invoke(0x6d616e,max_fee=int(1e16)))
print(result)
solution = (await riddleContract.functions["solution"].call()).solution
print("solution")
print(solution)
asyncio.get_event_loop().run_until_complete(getSolution())