Web3: realiza la función de contrato pero solo recibe el hash de la transacción o el valor incorrecto

Estoy tratando de hacer una demostración de una función en mi propia red de prueba geth. Implementé un contrato de muestra que encontré en http://solidity.readthedocs.io/en/develop/types.html?highlight=crowdfunding .

pragma solidity ^0.4.11;

contract CrowdFunding {
    // Defines a new type with two fields.
    struct Funder {
        address addr;
        uint amount;
    }

    struct Campaign {
        address beneficiary;
        uint fundingGoal;
        uint numFunders;
        uint amount;
        mapping (uint => Funder) funders;
    }

    uint numCampaigns;
    mapping (uint => Campaign) campaigns;

    function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
        campaignID = numCampaigns++; // campaignID is return variable
        // Creates new struct and saves in storage. We leave out the mapping type.
        campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
    }

    function contribute(uint campaignID) payable {
        Campaign storage c = campaigns[campaignID];
        // Creates a new temporary memory struct, initialised with the given values
        // and copies it over to storage.
        // Note that you can also use Funder(msg.sender, msg.value) to initialise.
        c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
        c.amount += msg.value;
    }

    function checkGoalReached(uint campaignID) returns (bool reached) {
        Campaign storage c = campaigns[campaignID];
        if (c.amount < c.fundingGoal)
            return false;
        uint amount = c.amount;
        c.amount = 0;
        c.beneficiary.transfer(amount);
        return true;
    }
}

"contrato" hace referencia al contrato desplegado. Configuré mi cuenta predeterminada y realicé la función newCampaign:

> contract.newCampaign(eth.accounts[0], 100)
"0x0122973cbcb7df227e8d625c6ee4a831d716b8b69398e4431ec14f89951fdc25"

Así que tengo la transacciónHash. Y se debería haber creado una nueva campaña para la dirección asociada a mi cuenta. Pero cuando trato de llamar a la función "checkGoalReached" siempre obtengo "true", aunque para mi campaña debería devolver falso dado que nadie ha contribuido.

(Probé tanto 0 como 1 porque se basa en la identificación)

> contract.checkGoalReached.call(0)
true
> contract.checkGoalReached.call(1)
true

Luego intenté enviar la transacción y registrar el resultado de esta función:

> contract.checkGoalReached(0, function(e, result) {console.log(result)})
0xe1bf7a275a62fb3bc2cdd12ff280cde5e9064ddbfeb51ba6713a713cd356c8cc
undefined
> contract.checkGoalReached(1, function(e, result){console.log(result)})
0x613c5973733cde57d4b7325bbab2d841d2fa6c95e371e77ca24a2f5a54768fd3
undefined

Se debe devolver "falso", por lo que debo estar haciendo algo mal en la consola web3. ¿Cuál es la forma correcta de probar estas funciones en la consola?

Respuestas (1)

Jugué con tu contrato en Remix para confirmar que hace lo que parece hacer. Tiene un comportamiento inesperado debido a la estructura de datos. Por ejemplo, para cualquier contrato indefinido devuelve trueporque 0no es menor que 0.

Por "ajustado", me refiero a una investigación sobre una campaña inexistente probablemente debería throwen lugar de arrojar un resultado engañoso. Podría considerar ajustar eso, usando una estructura mapeada con index. (¿ Existen patrones de almacenamiento sencillos y bien resueltos para Solidity? ).

De todos modos, confirmé que regresa falsecomo se esperaba con una nueva campaña con un objetivo de 100. Esto difiere de los resultados que obtienes al llamarlo, y creo que tiene que ver con tratar de usarlo de forma sincrónica.

Básicamente, tienes que esperar los resultados o te confundirá. Por ejemplo:

var contract;
MyContract.deployed().then(function(instance) { contract = instance; });

Ahora puede continuar con contractla representación de su contrato desplegado. Debe esperar a que regresen las promesas, así que inténtelo de esta manera:

contract.checkGoalReached().call(0).then(function(response) { console.log(response); });

Asumí que estás usando Truffle. :-)

Espero eso ayude.