aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain/vm.go
diff options
context:
space:
mode:
Diffstat (limited to 'ethchain/vm.go')
-rw-r--r--ethchain/vm.go59
1 files changed, 35 insertions, 24 deletions
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 909b375ae..fa839b260 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -617,48 +617,59 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case CREATE:
require(3)
- value := stack.Pop()
- size, offset := stack.Popn()
+ var (
+ err error
+ value = stack.Pop()
+ size, offset = stack.Popn()
- // Snapshot the current stack so we are able to
- // revert back to it later.
- snapshot := vm.state.Copy()
+ // Snapshot the current stack so we are able to
+ // revert back to it later.
+ snapshot = vm.state.Copy()
+ )
// Generate a new address
addr := ethcrypto.CreateAddress(closure.caller.Address(), closure.caller.N())
+ for i := int64(0); vm.state.GetStateObject(addr) != nil; i++ {
+ t := new(big.Int).Set(closure.caller.N())
+ addr = ethcrypto.CreateAddress(closure.caller.Address(), t.Add(t, big.NewInt(i)))
+ }
vm.Printf(" (*) %x", addr).Endl()
// Create a new contract
contract := vm.state.NewStateObject(addr)
- contract.Amount = value
-
- // Set the init script
- contract.initScript = ethutil.BigD(mem.Get(offset.Int64(), size.Int64())).Bytes()
- // Transfer all remaining gas to the new
- // contract so it may run the init script
- gas := new(big.Int).Set(closure.Gas)
-
- // Create the closure
- c := NewClosure(closure.caller,
- closure.Object(),
- contract.initScript,
- vm.state,
- gas,
- closure.Price)
- // Call the closure and set the return value as
- // main script.
- var err error
- c.Script, gas, err = c.Call(vm, nil)
+ if contract.Amount.Cmp(value) >= 0 {
+ closure.object.SubAmount(value)
+ contract.AddAmount(value)
+
+ // Set the init script
+ contract.initScript = ethutil.BigD(mem.Get(offset.Int64(), size.Int64())).Bytes()
+ // Transfer all remaining gas to the new
+ // contract so it may run the init script
+ gas := new(big.Int).Set(closure.Gas)
+ closure.UseGas(closure.Gas)
+
+ // Create the closure
+ c := NewClosure(closure, contract, contract.initScript, vm.state, gas, closure.Price)
+ // Call the closure and set the return value as
+ // main script.
+ c.Script, err, _ = Call(vm, c, nil)
+ } else {
+ err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount)
+ }
if err != nil {
stack.Push(ethutil.BigFalse)
// Revert the state as it was before.
vm.state.Set(snapshot)
+
+ vm.Printf("CREATE err %v", err)
} else {
stack.Push(ethutil.BigD(addr))
+ vm.Printf("CREATE success")
}
+ vm.Endl()
case CALL:
require(7)