diff options
author | obscuren <geffobscura@gmail.com> | 2014-07-02 23:47:09 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-07-02 23:47:09 +0800 |
commit | 40e3d2ab55f32c2458981533f5511e2f24a65c11 (patch) | |
tree | da82fc6f9dc930596b3e84eff661a09a3bde5aaf /ethchain/vm.go | |
parent | 6748158ab4e437a983988f5477a2bea56a20e009 (diff) | |
download | go-tangerine-40e3d2ab55f32c2458981533f5511e2f24a65c11.tar.gz go-tangerine-40e3d2ab55f32c2458981533f5511e2f24a65c11.tar.zst go-tangerine-40e3d2ab55f32c2458981533f5511e2f24a65c11.zip |
Changed CREATE
Diffstat (limited to 'ethchain/vm.go')
-rw-r--r-- | ethchain/vm.go | 59 |
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) |