Accediendo a una variable de mapeo desde web3

¿Hay alguna manera de acceder a una variable de mapeo como:

mapping(bytes => bool) myMappingVar;

que NO es:

  • Declarado público explícitamente
  • sin usar una identificación basada en índices
  • Además, no se establece ningún método getter público correspondiente.

Por ejemplo, desde web3:

contract.instance.methods.myMappingVar('somevalue').call();

Respuestas (3)

No convenientemente, pero puede acceder a cualquier valor en el almacenamiento de un contrato inteligente a través de web3.eth.getStorageAt. Consulte https://solidity.readthedocs.io/en/develop/miscellaneous.html#layout-of-state-variables-in-storage para obtener detalles sobre cómo se distribuye el almacenamiento.

Si your mappinges la primera variable de estado en el contrato, por lo que está en la ranura 0, este código recuperará el valor de la clave 0x123456.

var slot = "0".repeat(64);  // hex uint256 representation of 0
var key = "0x123456";  // hex representation of the key

web3.eth.getStorageAt(
  contractAddress,  // address of the contract to read from
  web3.sha3(key+slot, { encoding: 'hex' }),  // keccak256(k . p)
  function (err, result) {
    console.log(result);  // 00...0 for false, 00...1 for true, both 32 bytes wide
  }
);
¿Qué es la ranura? ¿Es un índice de la variable de mapeo?
"Ranura" es el nombre dado a la posición en el almacenamiento donde reside algún valor.
No entiendo. ¿Cómo obtengo una ranura para un mapeo con la clave 'altura' como: ``` ['edad': verdadero, 'nombre': verdadero, 'altura': verdadero] ``` también vea, mi pregunta dice sin usar o suponiendo que los índices son un valor conocido
Simplemente use key = web3.fromAscii('height')en el código anterior.
¡Voy a darle una oportunidad! Gracias. Pero, ¿cuál debería ser el valor de la ranura? 0?
Depende de dónde mappingse encuentre en su código Solidity. Si es la primera variable, entonces la ranura será 0. Si no, realmente tendrá que leer la documentación a la que me vinculé para obtener más detalles.
Ok lo tengo. Supuse que la ranura se refiere a un índice para la variable de mapeo

Puede acceder a una variable de asignación pública como una variable pública normal, con la excepción de que debe proporcionar el valor de índice para la asignación .

He hecho el siguiente ejemplo, y funcionó para mí.

En mi contrato escrito usando Solidity


address public owner; 
mapping(uint8 => address) public incomingQueue;
mapping(address => string) public assignedName;

Después de obtener la dirección del contrato:

const contract = web3.eth.contract(abiArray).at(contract_address);

Puedo acceder a estas variables usando el siguiente código javascript web3:


contract.owner.call(function(err, result){
     if(!err)
         alert(result)
 });
contract.incomingQueue.call(0, function(err, result){
     if(!err){
        alert(result)
     }
 });
contract.assignedName.call(web3.eth.accounts[0], function(err, result){
     if(!err){
        alert(result)
     }
 });
Usando este método, recibo el error No se puede leer la propiedad 'llamada' de indefinido
Esto es para versiones anteriores de web3. En la versión 1.2 de web3, debe llamarlo contract.methods.incomingQueue(0).call();

Desde la perspectiva de la ocultación de información, no puede acceder a los campos desde el exterior. Necesitas una función getter. Cuando especifica el modificador público en el mapeo, Solidity genera una función getter para usted.

Sin embargo, como explica Smarx en su respuesta, esto no protege sus datos para que no se lean directamente desde el almacenamiento.

Desde fuera del EVM, puede leer cualquier cosa almacenada en un contrato inteligente.
Oh... ¿estás asumiendo que la pregunta se hace desde la perspectiva de asegurar los datos? Entonces, por supuesto, "No puede acceder a los campos desde el exterior" está mal.
No estoy seguro de cuál es la perspectiva... la pregunta solo dice "hay alguna manera".
Votando tu respuesta tan pronto como me recuperé de "Vox Populi". ;-)
La respuesta de @smarx se inclina más hacia una posible respuesta.