4
votes

I have created an AccountManager smart contract and two instances of it(PARTYA and PARTYB). When calling TransferAgent.transfer(AccountManager.address, AccountManager.address) I can see accounts[msg.sender].balance update as expected. However, when calling the instances(PARTYA and PARTYB), for example, TransferAgent.transfer(PARTYA.address, PARTYB.address) there is no change reflected in the balance.

I have spent some time researching how to call AccountManager (instances) from TransferAgent (external contract) using addresses, but could not find anything specific to this. I am not able to get balance to reflect change. Any suggestions?

Environment - Ethereum - embark-framework - Solidity

My setup is below

contracts.json

    {
      "default": {
        "gas": "auto",
        "contracts": {
          "SimpleStorage": {
            "args": [
              100
            ]
          },
          "Agent" : {
            "args": [
            ]
          },
          "AccountManager" : {
            "args": [
            ]
          },
          "PARTYA" : {
            "instanceOf" : "AccountManager",
            "args" : [
            ]       
          },
          "PARTYB" : {
            "instanceOf" : "AccountManager",
            "args" : [
            ]       
          },
          "TransferAgent" : {
            "args": [
            ]
          }
        }
      }
    }

Agent.sol

pragma solidity ^0.4.0;

contract Agent {
/* Define variable owner of the type address*/
address owner;

/* this function is executed at initialization and sets the owner of the contract */
function Agent() { owner = msg.sender; }

/* Function to recover the funds on the contract */
function kill() { if (msg.sender == owner) selfdestruct(owner); }
}

contract AccountManager is Agent {
enum ACTIVE { Y, N } 
enum STATUS { CREDIT, DEBIT }
mapping (address => Account) public accounts;

struct Account {
    bytes32 ssn;
    int balance;
    ACTIVE active;
    STATUS status;
}

modifier withdrawValidation(int withdrawAmt) {
    if( withdrawAmt <= accounts[msg.sender].balance)  {
        throw;
    }
    _;
}

// Check for current account matching 
modifier transferValidation(address _from, address _to, bytes32 _ssn) {
    if( AccountManager(_from).getSSN() != _ssn || 
            AccountManager(_to).getSSN() != _ssn || 
                AccountManager(_from).getStatus() == STATUS.CREDIT )  {
        throw;
    }
    _;
}

function register(bytes32 _ssn) public returns (bool success) {
    Account memory newRegistree;
    newRegistree.ssn = _ssn;
    newRegistree.balance = 0;
    newRegistree.active = ACTIVE.Y;
    newRegistree.status = STATUS.DEBIT;
    accounts[msg.sender] = newRegistree;
    return true;
}

function update(bytes32 _ssn) public returns (bool success) {
    accounts[msg.sender].ssn = _ssn;
    return true;
}

function deposit(int _depositAmt) public returns(bool success) {
    accounts[msg.sender].balance += _depositAmt;
    return true;
}

function withdraw(int _withdrawAmt) public returns(bool success) {
    accounts[msg.sender].balance = (accounts[msg.sender].balance - _withdrawAmt);
    return true;
}

function getBalance() public constant returns(int balance) {
    return accounts[msg.sender].balance;
}

function setBalance(int _balance) external returns(bool success) {
    accounts[msg.sender].balance = _balance;
    return true;
}

function setStatus() internal {
    if(accounts[msg.sender].balance >= 0)
        accounts[msg.sender].status = STATUS.DEBIT;
    else 
        accounts[msg.sender].status = STATUS.CREDIT;
}

function getStatus() external constant returns (STATUS status) {
    return accounts[msg.sender].status;
}

function getSSN() external constant returns(bytes32 ssn) {
    return accounts[msg.sender].ssn;
}

function getAccount() public constant returns (bytes32 ssn, int balance, ACTIVE active, STATUS status) {
    return (accounts[msg.sender].ssn, accounts[msg.sender].balance, accounts[msg.sender].active, accounts[msg.sender].status);
}
}

contract TransferAgent is Agent {
function transfer(address _from, address _to) public returns (bool success) {
    AccountManager(_from).setBalance(100); // not working for instances PARTYA,PARTYB
    AccountManager(_to).setBalance(200); // not working for instances PARTYA,PARTYB    }
}
1

1 Answers

3
votes

Here's a very minimalist example that just concentrates on sending a transaction to another contract.

The "Hub" will deploy two "Spokes" and then you can use function local() to send messages to one of the spokes. Events are logged on both sides so you can see what's going on.

contract Hub {

  Spoke public A;
  Spoke public B;

  event LogTXNSent(address spoke);

  function Hub() {
    A = new Spoke();
    B = new Spoke();
  }

  function local(address spokeAddress)
    public
    returns(bool success)
  {
    if(spokeAddress != address(A) && spokeAddress != address(B)) throw;
    if(!Spoke(spokeAddress).logEvent()) throw;
    LogTXNSent(spokeAddress);
    return true;
  }

}

contract Spoke {

  event LogTXNFrom(address sender);

  function logEvent()
    public
    returns(bool success)
  {
    LogTXNFrom(msg.sender);
    return true;
  }
}

Hope it helps.