-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Re #253: Add transfer() and send() functionality to BlockchainRuntime
Added the functionality transfer, similar to call, except with no data field. Transfer is available to contract and to account. Added tests to verify the transfer of balance (including zero and negatives to behave as expected). Added a test that calls internal transaction for the transfer.
- Loading branch information
1 parent
3650f5b
commit a0931bc
Showing
6 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
156 changes: 156 additions & 0 deletions
156
org.aion.avm.core/test/org/aion/avm/core/TransferTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package org.aion.avm.core; | ||
|
||
import org.aion.avm.api.ABIEncoder; | ||
import org.aion.avm.api.Address; | ||
import org.aion.avm.core.bitcoin.Transaction; | ||
import org.aion.avm.core.testHashes.HashTestTargetClass; | ||
import org.aion.avm.core.util.AvmRule; | ||
import org.aion.avm.core.util.HashUtils; | ||
import org.aion.avm.core.util.Helpers; | ||
import org.aion.avm.core.util.TestingHelper; | ||
import org.aion.kernel.AvmTransactionResult; | ||
import org.aion.kernel.KernelInterfaceImpl; | ||
import org.aion.vm.api.interfaces.TransactionContext; | ||
import org.aion.vm.api.interfaces.TransactionResult; | ||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.spongycastle.util.encoders.Hex; | ||
|
||
import java.math.BigInteger; | ||
|
||
public class TransferTest { | ||
@Rule | ||
public AvmRule avmRule = new AvmRule(false); | ||
|
||
private long energyLimit = 10_000_000L; | ||
private long energyPrice = 1L; | ||
|
||
private org.aion.vm.api.interfaces.Address deployer = KernelInterfaceImpl.PREMINED_ADDRESS; | ||
private org.aion.vm.api.interfaces.Address dappAddress; | ||
|
||
private final String methodName = "doTransfer"; | ||
private final long dappInitialBalance = 10000; | ||
|
||
@Before | ||
public void setup() { | ||
byte[] txData = avmRule.getDappBytes(TransferTestTarget.class, null); | ||
dappAddress = avmRule.deploy(deployer, BigInteger.ZERO, txData, energyLimit, energyPrice).getDappAddress(); | ||
|
||
//send some balance to the dapp | ||
avmRule.kernel.adjustBalance(dappAddress, BigInteger.valueOf(dappInitialBalance)); | ||
} | ||
|
||
@Test | ||
public void testTransferNormal() { | ||
long energyLimit = 5000000; | ||
long transferBalance = 500; | ||
|
||
// receiver address | ||
org.aion.vm.api.interfaces.Address receiverAddress = Helpers.randomAddress(); | ||
avmRule.kernel.createAccount(receiverAddress); | ||
byte[] to = receiverAddress.toBytes(); | ||
|
||
// Call contract | ||
byte[] txData = ABIEncoder.encodeMethodArguments(methodName, to, transferBalance, energyLimit); | ||
TransactionResult txResult = avmRule.call(deployer, dappAddress, BigInteger.ZERO, txData, this.energyLimit, this.energyPrice).getTransactionResult(); | ||
Assert.assertEquals(AvmTransactionResult.Code.SUCCESS, txResult.getResultCode()); | ||
|
||
// check balance | ||
BigInteger contractBalance = avmRule.kernel.getBalance(dappAddress); | ||
System.out.println("contract balance is: " + contractBalance); | ||
Assert.assertEquals(dappInitialBalance - transferBalance, contractBalance.intValue()); | ||
|
||
BigInteger receiverBalance = avmRule.kernel.getBalance(receiverAddress); | ||
System.out.println("receiver balance is: " + receiverBalance); | ||
Assert.assertEquals(transferBalance, receiverBalance.intValue()); | ||
} | ||
|
||
@Test | ||
public void testTransferZero() { | ||
long energyLimit = 5000000; | ||
long transferBalance = 0; | ||
|
||
// receiver address | ||
org.aion.vm.api.interfaces.Address receiverAddress = Helpers.randomAddress(); | ||
avmRule.kernel.createAccount(receiverAddress); | ||
byte[] to = receiverAddress.toBytes(); | ||
|
||
// Call contract | ||
byte[] txData = ABIEncoder.encodeMethodArguments(methodName, to, transferBalance, energyLimit); | ||
TransactionResult txResult = avmRule.call(deployer, dappAddress, BigInteger.ZERO, txData, this.energyLimit, this.energyPrice).getTransactionResult(); | ||
Assert.assertEquals(AvmTransactionResult.Code.SUCCESS, txResult.getResultCode()); | ||
|
||
// check balance | ||
BigInteger contractBalance = avmRule.kernel.getBalance(dappAddress); | ||
System.out.println("contract balance is: " + contractBalance); | ||
Assert.assertEquals(dappInitialBalance - transferBalance, contractBalance.intValue()); | ||
|
||
BigInteger receiverBalance = avmRule.kernel.getBalance(receiverAddress); | ||
System.out.println("receiver balance is: " + receiverBalance); | ||
Assert.assertEquals(transferBalance, receiverBalance.intValue()); | ||
} | ||
|
||
@Test | ||
public void testTransferNegative() { | ||
long energyLimit = 5000000; | ||
long transferBalance = -10; | ||
|
||
// receiver address | ||
org.aion.vm.api.interfaces.Address receiverAddress = Helpers.randomAddress(); | ||
avmRule.kernel.createAccount(receiverAddress); | ||
byte[] to = receiverAddress.toBytes(); | ||
|
||
// Call contract | ||
byte[] txData = ABIEncoder.encodeMethodArguments(methodName, to, transferBalance, energyLimit); | ||
TransactionResult txResult = avmRule.call(deployer, dappAddress, BigInteger.ZERO, txData, this.energyLimit, this.energyPrice).getTransactionResult(); | ||
Assert.assertEquals(AvmTransactionResult.Code.FAILED_EXCEPTION, txResult.getResultCode()); | ||
|
||
// check balance | ||
BigInteger contractBalance = avmRule.kernel.getBalance(dappAddress); | ||
System.out.println("contract balance is: " + contractBalance); | ||
Assert.assertEquals(dappInitialBalance, contractBalance.intValue()); | ||
|
||
BigInteger receiverBalance = avmRule.kernel.getBalance(receiverAddress); | ||
System.out.println("receiver balance is: " + receiverBalance); | ||
Assert.assertEquals(0, receiverBalance.intValue()); | ||
} | ||
|
||
@Test | ||
public void testTransferInternal() { | ||
// call a dapp that calls another dapp to transfer value | ||
long energyLimit = 5000000; | ||
long transferBalance = 1000; | ||
String methodNameOuter = "callAnotherDappToTransfer"; | ||
|
||
// deploy 2nd dapp | ||
org.aion.vm.api.interfaces.Address dapp2Address; | ||
byte[] deployData = avmRule.getDappBytes(TransferTestTarget.class, null); | ||
dapp2Address = avmRule.deploy(deployer, BigInteger.ZERO, deployData, energyLimit, energyPrice).getDappAddress(); | ||
avmRule.kernel.adjustBalance(dapp2Address, BigInteger.valueOf(dappInitialBalance)); | ||
|
||
// generate receiver address | ||
org.aion.vm.api.interfaces.Address receiverAddress = Helpers.randomAddress(); | ||
avmRule.kernel.createAccount(receiverAddress); | ||
|
||
// Call contract | ||
byte[] txData2 = ABIEncoder.encodeMethodArguments(methodName, receiverAddress.toBytes(), transferBalance, energyLimit); | ||
byte[] txData = ABIEncoder.encodeMethodArguments(methodNameOuter, dapp2Address.toBytes(), txData2, energyLimit); | ||
|
||
TransactionResult txResult = avmRule.call(deployer, dappAddress, BigInteger.ZERO, txData, this.energyLimit, this.energyPrice).getTransactionResult(); | ||
Assert.assertEquals(AvmTransactionResult.Code.SUCCESS, txResult.getResultCode()); | ||
|
||
// check balance | ||
BigInteger contractBalance = avmRule.kernel.getBalance(dappAddress); | ||
BigInteger contract2Balance = avmRule.kernel.getBalance(dapp2Address); | ||
BigInteger receiverBalance = avmRule.kernel.getBalance(receiverAddress); | ||
|
||
System.out.println("contract balance is: " + contractBalance); | ||
Assert.assertEquals(dappInitialBalance, contractBalance.intValue()); | ||
System.out.println("contract2 balance is: " + contract2Balance); | ||
Assert.assertEquals(dappInitialBalance - transferBalance, contract2Balance.intValue()); | ||
System.out.println("receiver balance is: " + receiverBalance); | ||
Assert.assertEquals(transferBalance, receiverBalance.intValue()); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
org.aion.avm.core/test/org/aion/avm/core/TransferTestTarget.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package org.aion.avm.core; | ||
|
||
import org.aion.avm.api.ABIDecoder; | ||
import org.aion.avm.api.Address; | ||
import org.aion.avm.api.BlockchainRuntime; | ||
|
||
import java.math.BigInteger; | ||
|
||
public class TransferTestTarget { | ||
|
||
public void doTransfer(byte[] to, long balance, long energyLimit){ | ||
Address receiverAddress = new Address(to); | ||
BlockchainRuntime.transfer(receiverAddress, BigInteger.valueOf(balance), energyLimit); | ||
} | ||
|
||
public void callAnotherDappToTransfer(byte[] to, byte[] args, long energyLimit){ | ||
Address receiverAddress = new Address(to); | ||
BlockchainRuntime.call(receiverAddress, BigInteger.ZERO, args, energyLimit); | ||
} | ||
|
||
private static org.aion.avm.core.TransferTestTarget testTarget; | ||
|
||
/** | ||
* Initialization code executed once at the Dapp deployment. | ||
*/ | ||
static { | ||
testTarget = new org.aion.avm.core.TransferTestTarget(); | ||
} | ||
|
||
/** | ||
* Entry point at a transaction call. | ||
*/ | ||
public static byte[] main() { | ||
return ABIDecoder.decodeAndRunWithObject(testTarget, BlockchainRuntime.getData()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters