Solidity

將新的自定義操作碼添加到solidity

  • March 1, 2022

我在將新操作碼添加到solidity 時遇到問題。我正在使用 solc(在 C++ 上)和 geth(在 Go 上的乙太坊)。我想添加新的操作碼,它接受address payable, uint256, uint256, bytes memory並返回bytes memory. 所以我有返回值的問題。

下面的一些程式碼和平,我將跳過一些文件,以使問題更短。

  1. 索爾克
  • libsolidity/codegen/ExpressionCompiler.cpp
// ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::MyOpcode:
{
   acceptAndConvert(*arguments[0], *function.parameterTypes()[0], true);
   acceptAndConvert(*arguments[1], *function.parameterTypes()[1], true);
   acceptAndConvert(*arguments[2], *function.parameterTypes()[2], true);
   arguments[3]->accept(*this);
   utils().fetchFreeMemoryPointer();
   utils().packedEncode(
       {arguments[3]->annotation().type},
       {TypeProvider::array(DataLocation::Memory, true)}
   );
   utils().toSizeAfterFreeMemoryPointer();

   m_context << Instruction::MYOPCODE;
}
  • libsolidity/analysis/GlobalContext.cpp
// inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariables()
magicVarDecl("myopcode", TypeProvider::function(strings{"address payable", "uint256", "uint256", "bytes memory"}, strings{"bytes memory"}, FunctionType::Kind::MyOpcode, false, StateMutability::Payable)),
  • libevmasm/Instruction.cpp
// static std::map<Instruction, InstructionInfo> const c_instructionInfo =
{ Instruction::MYOPCODE,       { "MYOPCODE",          0, 5, 1, true, Tier::Base } }
  1. 格思
  • 核心/vm/jump_table.go
// func newFrontierInstructionSet() JumpTable {
CALLACTOR: {
   execute:    opMyOpCode,
   dynamicGas: gasCallActor,
   minStack:   minStack(5, 1),
   maxStack:   maxStack(5, 1),
   memorySize: memoryReturn,
   writes:     true,
   returns:    true,
},
  • 核心/vm/instructions.go
func opMyOpcode(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
   inoffset, insize := callContext.stack.pop(), callContext.stack.pop()
   params := callContext.memory.GetPtr(int64(inoffset.Uint64()), int64(insize.Uint64()))

   secondValue := callContext.stack.pop()

   firstValue := callContext.stack.pop()

   addr := callContext.stack.pop()

   // ... Do smth with input ...

   outoffset := inoffset.Uint64() + insize.Uint64()

   callContext.memory.Set(outoffset, 1, []byte{0x1})
   tmp := make([]byte, 1)
   tmp[0] = 0x98
   callContext.memory.Set(outoffset + 1, 1, tmp)

   callContext.stack.push(uint256.NewInt().SetUint64(outoffset))

   return tmp, nil
}
  1. 智能合約
pragma solidity >=0.6.0; // SPDX-License-Identifier: GPL-3
contract test {
   event ReturnValue(address payable _from, bytes data);
   function f() public returns(bytes memory){
       address payable addr1 = payable(msg.sender);
       bytes memory params = new bytes(2);
       params[0] = 0x21;
       params[1] = 0x22;
       bytes memory result = myopcode(addr1, 0x11, 0x12, params);
       emit ReturnValue(addr1, result);
       return result;
   }
}

當我執行該程式碼時,我得到invalid jump destination. 那麼,我需要做什麼才能讓我的程式碼正常工作?

我找到了一個解決方案,它看起來確實很愚蠢,但是開發人員已經提供了這個案例。你只需要utils().returnDataToArray().

引用自:https://ethereum.stackexchange.com/questions/93916