Избегайте цикла for и выполняйте вызов функции только один раз любым пользователем

pragma solidity ^0.4.17;
//  I want to write a code for  loyalty points when user pays 
contract GiveRefreceId {

    struct  referenceids {
        uint256 rid ;
        address addressrid;
}
    mapping(uint256 => referenceids) referenceid;
    referenceids[] lenrefrenceid;

function giveRefrenceId() public returns (uint256)  { 
    for (uint256 i=0 ;i<=lenrefrenceid.length; i++){

        require( lenrefrenceid[i]  != msg.sender);
    } 

    uint256 lenvarble = lenrefrenceid.length;

    referenceids  storage temprid = referenceid[lenvarble];

    temprid.rid = lenvarble;
    temprid.addressrid = msg.sender;
    lenrefrenceid.push(temprid);
    return lenvarble;
}

function  getrefrnceId()  view returns(uint256) {

return ((lenrefrenceid.length)-1);

}
}

1) Я написал функцию для предоставления идентификатора ссылки пользователю

2) Я хочу запретить пользователю вызывать giverefrenceidфункцию только один раз, поэтому я научил писать цикл for и проверять, присутствует ли адрес в массиве или нет.

3) но я получаю ошибку

Operator != not compatible with types struct GiveRefreceId.referenceids storage ref and address
        require( lenrefrenceid[i]  != msg.sender);

4) Я знаю, что он жалуется на то, что struct и require не могут быть использованы, но я не нашел другого варианта для проверки.

5) Газ будет стоить дороже, если число увеличится. Любой способ избежать цикла for и проверить, что пользователь вызывает функцию в первый раз.

6) Я не хочу писать две функции, я хочу получить идентификатор, используя одну функцию, есть ли способ?

не могли бы вы описать, что должен делать этот код? Я имею в виду основной функционал. Это выглядит слишком сложно, у вас есть структура, сопоставление этих структур, а также массив таких же структур.
Привет, Джейм, сначала спасибо за ваш ответ. Я пытаюсь дать идентификатор ссылки пользователю, и я хочу использовать этот идентификатор ссылки, чтобы дать некоторые очки лояльности в следующей части кода, пока я учил давать идентификатор ссылки с длиной массива. было бы хорошо, чтобы я мог получить адрес рефрира и дать очки лояльности, и я хочу ограничить вызов функции только один раз любым пользователем
Смотрите мой ответ и дайте мне знать.
Нет, это не работает, пожалуйста, посмотрите следующую ссылку remix.ethereum.org/…

Ответы (1)

Код ниже должен сделать.

Функция giveReferenceIdприсваивает идентификатор пользователю на основе адреса. Массив clientsсохраняет список пользователей (на тот случай, если вам понадобится этот список в какой-то момент).

Чтобы убедиться, что один и тот же адрес получает только один идентификатор, используется строка: require(referenceid[msg.sender]==0);, поскольку 0 является недопустимым идентификатором, что означает, что пользователь не зарегистрирован.

Функция getrefrnceId() возвращает идентификатор пользователя, выполнившего функцию.

pragma solidity ^0.4.25;

contract GiveRefreceId {

    mapping(address => uint256) public referenceid;
    address[] public clients;
    uint256 idcounter;

    event createdId(address user, uint256 id);

    function giveRefrenceId() public returns (uint256)  { 
        require(referenceid[msg.sender]==0);
        idcounter += 1;
        clients.push(msg.sender);
        referenceid[msg.sender] = idcounter;
        emit createdId(masg.sender,idcounter);
        return idcounter;

    }


    function  getrefrnceId() public view returns(uint256) {
        return referenceid[msg.sender];
    }
}

Надеюсь это поможет

Извините, это не работает с одним и тем же идентификатором, я могу создать 2 идентификатора ссылки remix.ethereum.org/…
Вы имеете в виду, что с одним и тем же адресом вы можете зарегистрировать два разных идентификатора? Это невозможно. Кроме того, я запускаю это в ремиксе, если вы попытаетесь выполнить giveReferenceId дважды с одним и тем же адресом, транзакции отменяются.
Нет, я хочу, чтобы пользователь вызывал функцию Give refrence id() только один раз, когда он не сможет вызывать ее дважды.
Вы, кажется, в замешательстве. Вы не можете запретить пользователю вызывать функцию, что вы можете сделать, так это отклонить вызов, вернувшись, если субъект уже вызвал его, чтобы он / она не создавал два разных идентификатора с одним и тем же адресом, и это именно то, что делает контракт.
Спасибо, Джон, мне нужна такая же функциональность, что вы можете сделать, это отклонить вызов, вернув его, если субъект уже вызвал его, чтобы он / она не создавал два разных идентификатора с одним и тем же адресом, и это именно то, что делает контракт Но просто посмотрите транзакции на etherscan с тем же адресом, который я вызывал 3 раза и сгенерировал 2 идентификатора.
дайте мне адрес, где вы развернули контракт
0x0dd87fe70e4ed0af92f656396e9b7949aeb33cfc
Эй, контракт, который вы развернули, не тот контракт, который я разместил в своем ответе, что это за контракт?
Извините, я работал с предыдущим экземпляром транзакции
Нет проблем, такие вещи случаются, если это решило ваш вопрос, примите ответ.
не могли бы вы объяснить эту строку кода require(referenceid[msg.sender]==0); и как читать данные из логов без написания второй функции
referenceid — это сопоставление, по умолчанию значения равны нулю (0). В этом случае, если я сопоставляю адрес пользователя, возвращаемое значение равно нулю, если адрес не был зарегистрирован, поэтому требование спрашивает, равно ли значение сопоставления 0, а если нет, оно отменяет выполнение без назначения нового идентификатора. Что вы подразумеваете под «как читать данные из журналов, не записывая вторую функцию?», какие данные? есть вторая функция getrefrnceId(), которая возвращает идентификатор пользователя, который ее вызывает. это то, что вы имели ввиду?
Извините, Джеймс, за длинное обсуждение. Можем ли мы увидеть идентификатор, не записывая функцию getrefrnceId()?