То, что я пытаюсь достичь, похоже на то, что я должен иметь возможность динамически вызывать набор функций прочности на основе некоторых критериев. я использую метод call() для достижения того же.
(bool success, bytes memory result) =APContract.call(abi.encodeWithSignature(string(data), "hello"));
data
переменная содержит строку вызова функции "testCall(string)". вместо кодирования из контракта я должен иметь возможность кодировать то же самое с помощью javascript (из-за некоторой логики генерации аргументов). так что я могу вызвать функцию как APContract.call(data)
. Есть ли какой-нибудь метод, который поможет добиться того же?
Не уверен, что полностью понял ваш вопрос, но вы можете взглянуть на спецификацию ABI контракта Solidity Documentation: https://docs.soliditylang.org/en/latest/abi-spec.html#examples .
Чтобы увидеть, как кодировать параметры самостоятельно. По сути, это большой набор связанных строк, состоящий из хэша имени функции и аргументов функции.
Вы также можете взглянуть на эту библиотеку, которая выполняет «вызовы пользовательских контрактов» (поэтому не полагаясь на какой-либо ABI): https://github.com/ERC725Alliance/erc725.js/blob/main/src/lib/utils.ts .
import Web3 from 'web3';
const web3 = new Web3();
const methodId = web3.utils.keccak256('testCall(string)').substr(0, 10); //0xc7cee1b7
// In this function call, the first and only parameter uses a dynamic type: string
// https://docs.soliditylang.org/en/latest/abi-spec.html#use-of-dynamic-types
// we use the offset in bytes to the start of their data area, measured from the start of the value encoding
// offset to start of data part of second parameter, 1*32 bytes, exactly the size of the head part
const stringArgument = web3.utils.padLeft(web3.utils.toHex(1*32), 64).replace('0x', '');
// 0000000000000000000000000000000000000000000000000000000000000020
const stringValue = 'TODO' // This one is a bit tricky, the docs explain it well: https://docs.soliditylang.org/en/latest/abi-spec.html#use-of-dynamic-types
const call = methodId + stringArgument + stringValue;
Вы всегда можете создать свой собственный ABI dict, тогда web3 выполнит вышеуказанное преобразование за вас:
const contract = new web3.eth.Contract(
[
{
name: 'testCall',
inputs: [
{ type: 'bytes32', name: '_hash', internalType: 'bytes32' },
],
},
],
contractAddress,
);
const answer = await contract.methods
.testCall(messageHash)
.call();
Используйте вспомогательные функции из: https://web3js.readthedocs.io/en/v1.3.0/web3-eth-abi.html , чтобы создать то, что вам нужно.
web3.eth.abi.encodeParameter('string', 'Hello')
Изменить: вы также можете проверить исходный код web3
abi.encodeWithSignature("testCall(string)", "hello")
. и закодированные байты будут переданы параметром функции солидности (будет вызовом web3). эта конкретная функция будет вызывать как aPContract.call(data)
. data
закодированные байты пришли в качестве аргумента вызываемой функции. Будет полезно, если вы будете вести себя таким образомВот что я использовал для взлома уровня Ethernaut Puzzle Wallet . Я считаю, encodeFunctionCall
что это именно то, что вы ищете:
let deposit = web3.eth.abi.encodeFunctionCall(contract.abi[2], [])
let multicall = web3.eth.abi.encodeFunctionCall(contract.abi[6], [[deposit]])
let calldata = web3.eth.abi.encodeFunctionCall(contract.abi[6], [[deposit, multicall]])
await sendTransaction({
from: player,
to: instance,
value: web3.utils.toWei('0.001', "ether"),
data: calldata
})
Рашик Кодаккад
abi.encodeWithSignature("testCall(string)", "hello")