Contract-Development
在 ethereumj 中使用建構子創建合約
contract Calculator{ int result; function Calculator(int initialResult){ result=initialResult; } }
如果上面是我創建的合約原始碼,那麼如何使用 ethereumj API 呼叫 Calculator 函式。我已經用過
contract.callFunction("Calculator", 10)
但這沒有用。也被稱為
contract.callConstFunction("Calculator", 10)
但這也不起作用。
當看到 ABI 時,它的函式類型為 =“constructor”,但找不到任何表示呼叫建構子的方法。
請建議是否有任何方法可以呼叫建構子?
我終於找到了解決方案。正如另一個答案中所討論的,您需要在發送交易之前解析初始化參數並將其附加到合約程式碼中。我實際上並沒有找到一種優雅而通用的方式來直接在 Java 中解析參數(但應該不難做到)所以我將 ABI 語法解碼為字節
$$ $$. 首先複製 StandaloneBlockchain.java 並添加一個方法(對不起,我找不到通過擴展的簡單方法):
public SolidityContract submitNewContract(String soliditySrc, String contractName, byte[] initParameters) { SolidityContractImpl contract = createContract(soliditySrc, contractName); submitNewTx(new PendingTx(new byte[0], BigInteger.ZERO, ByteUtil.merge(Hex.decode(contract.getBinary()), initParameters), contract, null)); return contract; }
然後在 StandaloneBlockchainSample.java 中,引用修改後的類,修改範例合約以在建構子中有 2 個參數(我沒有時間檢查所有類型,但它應該可以正常工作)並分配參數 init 值:
// Pretty simple (and probably the most expensive) Calculator private static final String contractSrc = "contract Calculator {" + " int public result;" + // public field can be accessed by calling 'result' function " string testString;" + " bool testBool;"+ " function add(int num) {" + " result = result + num;" + " }" + " function sub(int num) {" + " result = result - num;" + " }" + " function mul(int num) {" + " result = result * num;" + " }" + " function div(int num) {" + " result = result / num;" + " }" + " function clear() {" + " result = 0;" + " }" + " function getString() constant returns (string) { return testString; }" + " function getBool() constant returns (bool) { return testBool; }" + " function Calculator(string _testString, bool _testBool){" + " testString = _testString;" + " testBool = _testBool;" + " }" + "}"; [...] String parameters = "{ 'inputs': [ { 'name': '_test', 'type': 'string' }, { 'name': '_test2', 'type': 'bool' } ] }".replaceAll("'", "\""); byte[] initParameters = CallTransaction.Function.fromJsonInterface(parameters).encodeArguments("Test", true); SolidityContract calc = bc.submitNewContract(contractSrc, null, initParameters); System.out.println("Calculating...");
之後,檢查參數的正確值:
assertEqual("Test", (String) calc.callConstFunction("getString")[0]); assertEqual(true, (boolean) calc.callConstFunction("getBool")[0]);
請注意,您需要修改類中的私有assertEqual方法,以斷言除了已定義的 BigInteger 之外的其他類型。我用 EthereumJ 1.2.0 測試了這個解決方案:也許下一個版本將包含一個更好的方法來將 init 值傳遞給建構子,所以如果你知道這一點,請更新答案。
你不需要呼叫建構子,你需要送出合約,你會自動擁有一個指向合約的指針,這樣:
StandaloneBlockchain bc = new StandaloneBlockchain().withAutoblock(true); bc.createBlock(); SolidityContract contract = bc.submitNewContract(contractSrc); System.out.println(contract.callConstFunction("result")[0]);
您可以在github上看到一個簡單但完整的工作範例