Как вы можете разделить определение структуры между контрактами в отдельных файлах?

Я не могу объявить автономную структуру в собственном файле, что дает?

Ответы (3)

С библиотекой можно! Вот пример:

pragma solidity ^0.4.17;

library SharedStructs {
    struct Thing {
        address[] people;
    }    
}

contract A {
    SharedStructs.Thing thing;
}

contract B {
    SharedStructs.Thing thing;
}

Следует помнить о двух важных вещах: 1) библиотека развертывается в цепочке, а затем на нее ссылаются по ее адресу, и 2) библиотека действует как настоящий сквозной канал, то есть msg.sender (и связанные значения) ссылаются на оригинальный звонилка.

Дополнительная информация и подробности здесь: http://solidity.readthedocs.io/en/develop/contracts.html#libraries

Вы уверены, что необходимо развернуть библиотеку, если вы хотите поделиться определением структуры ? Я думаю, что в этом случае вы можете использовать библиотеку, не развертывая ее и не связывая с контрактами.

Если вы не хотите использовать библиотеки, вы можете создать абстрактный контракт, который содержит только наследуемые от них структуры. Это довольно уродливо, если контракты не совсем связаны.

contract GeometryShapesData {
    struct Point {
        uint x;
        uint y;
    }
}

contract A is GeometryShapesData {
    mapping (bytes32 => Point) public points;
    function addPoint(bytes32 idx, uint x, uint y) public { 
        points[idx] = Point(x, y);
    }
    function getPoint(bytes32 idx) constant public returns (uint x, uint y) {
        return (points[idx].x, points[idx].y);
    }
}

contract B is GeometryShapesData {
    Point[4] public vertexes;
    function addVertex(uint pos, uint x, uint y) public { 
        vertexes[pos] = Point(x, y);
    }
    function getVertex(uint pos) constant public returns (uint x, uint y) {
        return (vertexes[pos].x, vertexes[pos].y);
    }
}
Именно потому, что некрасиво «злоупотреблять» наследованием таким образом, правильнее использовать это из библиотеки в режиме «реализует интерфейс» через библиотеку.

По крайней мере, в текущих версиях Solidity (^0.5.1), в зависимости от ваших потребностей, вы можете обойти необходимость явного определения структуры с помощью распаковки кортежа:

contract A {
    struct Thing {
        uint x;
        uint y;
        uint z;
    }
    mapping(uint => Thing) public foo;
    ...
}

import { A } from "./A.sol";
contract B {
    A a;
    constructor(A _a) public { a = _a; }
    function getY(uint id) public returns(uint) {
        (,uint ans,) = a.foo(id);
        return ans;
    }
}

Вы также можете найти этот и этот связанные посты полезными.