Assignment - More Randomness

Regardless if you have the simple or advanced DNA/Gene algorithm, I want you to make some modifications.

For those of you that have kept the simple algorithm: Add one more level of mixing into your algorithm. Get creative and see if you can find some other way of mixing the DNA’s instead of just combining the two halves.

For those of you that built the advanced algorithm: I mentioned in the last video that you can implement even more randomness to spice things up even more. That’s exactly what I want you to do.

Take the random number we calculated in the previous video, and use it to select one of the pairs that will get an extra randomness treatment. Then generate a new, 2 digit, random number and set it as that pair. That DNA pair will now be completely random, independent from any parent.

Post your code below

1 Like

Hey guys, my DNA string is 18 digits long so i used uint9 which I’m not sure is allowed. Remix threw an error which i have screen shotted below. Is there a way around this or should i shorten my DNA string?

function mixDna(uint256 _dadDNA, uint256 _mumDNA) internal view returns(uint256){
    uint256[9] memory geneArray;
    //sudo random number
    uint9 random = uint9(uint256(keccak256(block.timestamp, block.difficulty))%511); //binary between 000000000-111111111
    
    uint256 index = 8;
    for(i = 0; i <= 256; i=i*2){ //1, 2, 4, 8, 16, 32, 64, 128, 256 = 9 pairs
        if(random & i != 0){
            geneArray[index] = uint9( _mumDNA % 100);
        }else{
            geneArray[index] = uint9( _dadDNA % 100);
        }
            _mumDNA = _mumDNA / 100;//removing the last two digits by moving the decimal point
            _dadDNA = _dadDNA / 100;
            index = index -1; 
    }
    uint256 newGene;
    for(i = 0; i < 9; i++){
        newGene = newGene + geneArray[i];
        if(i != 8){
            newGene = newGene *100;
        }
    }
    return newGene;
}

Screenshot 2021-04-24 at 15.45.48

Screenshot 2021-04-24 at 15.48.56

1 Like

Hey @ol_frank uint9 is not allow. 2021-04-25_16h37_46
From solidity docs : https://docs.soliditylang.org/en/v0.5.3/types.html
Read directly documentation is a very fast way to improve and understand from the base.

1 Like

@AdamFortuna

Can you give me a hint on how to use the random number to determine which position of the newGene should be random as well? I can’t fully grasp how to do that.

Well, in my case i choose like the last digit of DNA to have it random. So it is like special stuff not coming from dad or mum. Example for 2 digit random number :

    function randomNum() returns (uint256){
        uint256 randNumber = now % 100;
        return randNumber 
    }

Then you just add this result to the end of DNA like a special trait

I’ve kept the simple algorithm and added a completely random animation.

function _mixDna(uint256 _dadDna, uint256 _mumDna)
        internal
        view
        returns (uint256)
    {
        uint256 dadPart = _dadDna / 100000000;
        uint256 mumPart = _mumDna % 100000000;

        uint256 newDna = (dadPart * 100000000) + mumPart;

        // Make animation completely Random I have implemented 1-7 types so I'll limit to that

        uint8 random = uint8(block.timestamp % 7) + 1;

        uint256 removeBit = newDna % 100;

        newDna = (newDna - removeBit) + (random * 10) + 1;

        return newDna;
    }
1 Like

Hello I have a question about Filip’s dna mixing algorithm.
I don’t understand why he uses 8 bits.

His cat DNA looks like this: 10, 13, 96, 10, 1, 1, 13, 13, 1, 1
Notice that there are 4 pairs for colors, 5 pairs for cattributes, and 1 pair for the last unknown digit. Therefore, there are 10 pairs in total.
However, in the video he used 8 bits. What’s also interesting is that some part of the DNA have only 1 digit. So diving by 100 and multiplying by 100 shouldn’t always work.

I don’t understand why and how it works.

DNA mixing code
function _mixDna(uint256 _dadDna, uint256 _mumDna) internal view returns(uint256){
  uint256[8] memory geneArray;
  uint8 random = uint8( block.timestamp % 255 );
  uint i;
  uint256 index = 7;
  for(i = 1; i <= 128; i *= 2){
    if(random & i != 0){
      geneArray[index] = uint8(_mumDna % 100);
    }else{
      geneArray[index] = uint8(_dadDna % 100);
    }
    _mumDna /= 100;
    _dadDna /= 100;
    index -= 1;
  }
  uint256 newGene;
  for(i = 0; i < 8; i++){
    newGene += geneArray[i];
    if(i != 7){
      newGene *= 100;
    }
  }
  return newGene;
}

@kenn.eth

2 Likes

After a few hours of work, I think I got it:

function _mixDna(uint256 _dadDna, uint256 _mumDna) internal view returns(uint256 newGene){
  uint256[] memory geneArray = new uint256[](10);
  uint8[10] memory digitControl = [100, 100, 100, 100, 10, 10, 10, 100, 10, 10]; 
  uint16 random = uint16(uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty))) % 65536);
  uint16 i;
  uint16 index = 10;
  for(i = 1; i <= 512; i = i * 2){
    index = index - 1;
    if(index == random % 10){
      geneArray[index] = (_mumDna % digitControl[index] + _dadDna % digitControl[index]) / 2;
    }else if(random & i != 0){
      geneArray[index] = _mumDna % digitControl[index];
    }else{
      geneArray[index] = _dadDna % digitControl[index];
    }
    _mumDna /= digitControl[index];
    _dadDna /= digitControl[index];
  }
  for(i = 0; i < 10; i++){
    newGene += geneArray[i];
    if(i != 9){
      newGene *= digitControl[i+1];
    }
  }
}

Feature:

  1. The random variable is more random. It takes block.timestamp and block.difficulty as parameters and hash it. Idea from @ol_frank.
  2. Compatible with one digit gene.
  3. When index is equal to the last digit of random, it takes average of dad gene and mum gene. This can happen only once in the for loop.

Full code: https://github.com/REGO350/nftgame

3 Likes

Hey @REGO350 ! There is many ways to mix DNA, some more complex than other. What we are doing here is to take parth of both DNA’s and mix it. But this way will not create similar cats that share some Attributes from parents. The form we mix, will depend on your styles and number of Attriubtes that act on the DNA. Lets say that is somethin thatg you can think of how you want to mix it. Depending on your style set.

1 Like

Hello this is my solution. Its simple but works if i is even the part for the number (example 10)of Dad dna wins and in the next count mom dna will win and then dad dna wins until the count is finished. I prefer not to make something very complicated because i understand is much better to use real randomness from oracles
My new code for _mixDna

function _mixDna(uint256 _dadDna, uint256 _mumDna) internal pure returns (uint256){
        uint256 mod= 10000000000000000;

        uint256 div= 100000000000000;

        uint256 newDna= 0;

        uint i;

        for (i=1; i<=8; i++){

            if(i%2==0) {// _dadDna wins 

            newDna = (newDna*100)+((_dadDna%mod)/div);

            }

            else { // _mumDna wins

            newDna = (newDna*100)+((_mumDna%mod)/div);

            }

            mod = mod/100;

            div = div/100;

        }

        return newDna;

    }


first pair of cats

image

second pair of cats
image

children
image

3 Likes

Hi all,

I have a question about an error I get. See the screenshot down below:

Schermafbeelding 2021-06-30 om 16.49.14

I tried several variations on the visibility of the getKitty function but can not solve it.

Here is my code:

Can someone tell me what I’ve been missing?

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

import "./IERC721.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";
import "./IERC721Receiver.sol";

 contract Kittycontract is IERC721, Ownable {

    uint256 public constant CREATION_LIMIT_GEN0 = 10;
    string private constant tokenName = "ThomasKitties";
    string private constant tokenSymbol = "TM";

    bytes4 internal constant MAGIC_ERC721_RECEIVED= bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));

    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; 

    struct Kitty {
        uint256 genes;
        uint64 birthTime;
        uint32 mumId;
        uint32 dadId;
        uint16 generation;
    }

    event Birth(
        address owner, 
        uint256 kittenId, 
        uint256 mumId,
        uint256 dadId,
        uint256 genes
    ); 


    Kitty[] kitties;

    mapping(uint256 => address) public kittyIndexToOwner;
    mapping(address => uint256) ownershipTokenCount;
    mapping (uint256 => address) public kittyIndexToApproved;
    mapping (address => mapping (address => bool)) private _operatorApprovals;

    uint256 public gen0Counter;

    function breed(uint256 _dadId, uint256 _mumId) public returns (uint256) {
        require(_owns(msg.sender, _dadId), "The user doesn't own the token");
        require(_owns(msg.sender, _mumId), "The user doens't own the token");

        ( uint256 dadDna,,,,uint256 DadGeneration ) = getKitty(_dadId);
        ( uint256 mumDna,,,,uint256 MumGeneration ) = getKitty(_mumId);

        uint256 newDna = _mixDna(dadDna, mumDna);

        uint256 kidGen = 0;
        if (DadGeneration < MumGeneration){
            kidGen = MumGeneration + 1;
            kidGen /= 2;
        } else if (DadGeneration > MumGeneration){
            kidGen = DadGeneration + 1;
            kidGen /= 2;
        } else {
            kidGen = MumGeneration + 1;
        }
        
        _createKitty(_mumId, _dadId, kidGen, newDna, msg.sender);
        
    }

    function supportsInterface(bytes4 _interfaceId) external pure returns (bool){
        return (_interfaceId == _INTERFACE_ID_ERC721 || _interfaceId == _INTERFACE_ID_ERC165);
    }

    function safeTransferFrom(address _from, address _to, uint256 _tokenId) public override {
        safeTransferFrom(_from, _to, _tokenId, "");
    }

    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public override {
        require( _isApprovedOrOwner(msg.sender, _from, _to, _tokenId) );
        _safeTransfer(_from, _to, _tokenId, _data);
    }

    // function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public override {
    //     require( _isApprovedOrOwner(msg.sender, _from, _to, _tokenId) );
    //     _safeTransfer(_from, _to, _tokenId, _data);
    // } 

    function _safeTransfer(address _from, address _to, uint256 _tokenId, bytes memory _data) internal {
        _transfer(_from, _to, _tokenId);
        require( _checkERC721Support(_from, _to, _tokenId, _data) );
    }
    
    function transferFrom(address _from, address _to, uint256 _tokenId) public override {
        require(_isApprovedOrOwner(msg.sender, _from, _to, _tokenId));
        // require(_to != address(0));
        // require(msg.sender == _from || _approvedFor(msg.sender, _tokenId) || isApprovedForAll(_from, msg.sender));
        // require(_owns(_from, _tokenId));
        // require(tokenId < kitties.length);

        _transfer(_from, _to, _tokenId);
    }

    function approve(address _to, uint256 _tokenId) public override {
        require(_owns(msg.sender, _tokenId));

        _approve(_tokenId, _to);
        emit Approval(msg.sender, _to, _tokenId);
    }

    function setApprovalForAll(address operator, bool approved) public override{
        require(operator != msg.sender);

        _operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function getApproved(uint256 tokenId) public view override returns (address){
        require(tokenId < kitties.length); //Token must exist

        return kittyIndexToApproved[tokenId];
    }

    function isApprovedForAll(address owner, address operator) public view override returns (bool){
        return _operatorApprovals[owner][operator];
    }

    

    function getKitty(uint256 _id) external view returns(
        uint256 genes,
        uint256 birthTime,
        uint256 mumId,
        uint256 dadId,
        uint256 generation
    )
    {
        Kitty storage kitty = kitties[_id];

        birthTime = uint256(kitty.birthTime);
        mumId = uint256(kitty.mumId);
        dadId = uint256(kitty.dadId);
        generation = uint256(kitty.generation);
        genes = kitty.genes; 
    }



    function createKittyGen0(uint256 _genes) public onlyOwner returns (uint256){
        require(gen0Counter < CREATION_LIMIT_GEN0);
    
        gen0Counter++;

        // Gen0 have no owners they are own by the contract
        return _createKitty(0, 0, 0, _genes, msg.sender);
    
    }



    function _createKitty(
        uint256 _mumId,
        uint256 _dadId,
        uint256 _generation,
        uint256 _genes,
        address _owner
    ) public returns (uint256) {
        Kitty memory _kitty = Kitty({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            mumId: uint32(_mumId),
            dadId: uint32(_dadId),
            generation: uint16(_generation)
        });

        // uint256 newKittenId = kitties.push(_kitty) -1;
        kitties.push(_kitty);
        uint256 newKittenId = kitties.length - 1;

        _transfer(address(0), _owner, newKittenId);
    
        emit Birth(_owner, newKittenId, _mumId, _dadId, _genes);

    return newKittenId;
    }

    
    function balanceOf(address _owner) external view override returns (uint256 balance){
        return ownershipTokenCount[_owner];
    }

    function totalSupply() external view override returns (uint){
        return kitties.length;
    }

    function name() external pure override returns (string memory){
        return tokenName;
    }

    function symbol() external pure override returns (string memory){
        return tokenSymbol;
    }

    function ownerOf(uint256 _tokenId) external view override returns (address owner){
        return kittyIndexToOwner[_tokenId];
    }

    function transfer(address _to, uint256 _tokenId) external override {
        require(_to != address(0));
        require(_to != address(this));
        require(_owns(msg.sender, _tokenId));

        _transfer(msg.sender, _to, _tokenId);

    }

    function _transfer(address _from, address _to, uint256 _tokenId) internal{
        ownershipTokenCount[_to]++;

        kittyIndexToOwner[_tokenId] = _to;

        if(_from != address(0)) {
            ownershipTokenCount[_from]--;
            delete kittyIndexToApproved[_tokenId];
        }

        emit Transfer(_from, _to, _tokenId);
    }

    function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return kittyIndexToOwner[_tokenId] == _claimant;
    }

    function _approve(uint256 _tokenId, address _approved) internal {
        kittyIndexToApproved[_tokenId] = _approved;
    }

    function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return kittyIndexToApproved[_tokenId] == _claimant;
    }

    function _checkERC721Support(address _from, address _to, uint256 _tokenId, bytes memory _data) internal returns (bool){
        if( !_isContract(_to) ){
            return true;
        }
        //Call on ERC721Received in the _to contract
        bytes4 returnData = IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
        return returnData == MAGIC_ERC721_RECEIVED;
        //Check return value
    }

    function _isContract(address _to) view internal returns (bool){
        uint32 size;
        assembly{
            size := extcodesize(_to)
        }
        return size > 0;
    }

    function _isApprovedOrOwner(address _spender, address _from, address _to, uint256 _tokenId) internal view returns (bool){
        require(_tokenId < kitties.length); //Token must exist
        require(_to != address(0)); //To address is not zero address
        require(_owns(_from, _tokenId)); //From owns the token

        //msg.sender is from OR spender is approved for tokenId OR spender is operator for from
        return (_spender == _from || _approvedFor(_spender, _tokenId) || isApprovedForAll(_from, _spender)); 
}
    function _mixDna(uint256 _dadDna, uint256 _mumDna) internal returns (uint256){
        //dadDna: 11 22 33 44 55 66 77 88 
        //momDna: 88 77 66 55 44 33 22 11

        uint256 firsthalf = _dadDna/ 100000000; //11223344
        uint256 secondhalf = _mumDna % 100000000; //44332211

        uint256 newDna = firsthalf * 100000000;
        newDna = newDna + secondhalf; //which makes 1122334444332211
        return newDna;
    }

}

1 Like

Hey @thomascarl, hope you are ok.

Have you tried to change its visibitily from external to public or internal for example?

Carlos Z

Hi Carlos,

Thanks for your quick response. I changed the visibility to public and added pure to the _mixDna function. I now have the following error:

Schermafbeelding 2021-07-01 om 11.36.48

1 Like

hey @thomascarl ! I notice that in your breed function you are using returns (uint256) on definition but not returning anything at end of the function. So just make sure to return the id for example if is need or not return anything is also ok. Use returns in case you want to use it for something else.

2 Likes

I’ve built the advanced breeding algorithm. Have a look at my _mixGenes function in my code below.

Code

Kitties.sol
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Kitties is ERC721Enumerable, Ownable {
struct Kitty {
  uint256 genes;
  uint64 birthTime;
  uint32 mumId;
  uint32 dadId;
  uint16 generation;
}
Kitty[] private _kitties;

// Cap of how many generation 0 kitties can be created.
uint8 public constant GEN0_CAP = 10;
uint8 private _gen0Counter;

constructor() ERC721("Kitties", "KITS") {}

event Birth(
  address indexed owner,
  uint256 indexed kittyId,
  uint256 mumId,
  uint256 dadId,
  uint256 genes
);

// Breads a new kitty from two other kitties.
function breed(uint256 mumId, uint256 dadId) public {
  // '_isApprovedOrOwner' includes check whether token exists
  require(
    _isApprovedOrOwner(msg.sender, mumId) &&
      _isApprovedOrOwner(msg.sender, dadId),
    "Unauthorized"
  );

  Kitty storage mum = _kitties[mumId];
  Kitty storage dad = _kitties[dadId];
  uint256 newGenes = _mixGenes(mum.genes, dad.genes);
  uint16 newGeneration = _mixGeneration(mum.generation, dad.generation);

  _createKitty(mumId, dadId, newGeneration, newGenes, ownerOf(mumId));
}

// Creates a generation 0 kitty.
function createKittyGen0(uint256 genes) public onlyOwner {
  require(
    _gen0Counter <= GEN0_CAP,
    "All generation 0 kitties have already been created."
  );
  _gen0Counter++;
  _createKitty(0, 0, 0, genes, owner());
}

// Returns how many generation 0 kitties have already been created.
function countKittiesGen0() public view returns (uint256) {
  return uint256(_gen0Counter);
}

// Returns 'kittyId' kitty data.
function getKitty(uint256 kittyId)
  public
  view
  returns (
    uint256 genes,
    uint256 birthTime,
    uint256 mumId,
    uint256 dadId,
    uint256 generation
  )
{
  require(_exists(kittyId), "Nonexistent");
  Kitty storage kitty = _kitties[kittyId];

  genes = kitty.genes;
  birthTime = kitty.birthTime;
  mumId = kitty.mumId;
  dadId = kitty.dadId;
  generation = kitty.generation;
}

// ----- NONPUBLIC FUNCTIONS -----

function _mixGeneration(uint16 generation1, uint16 generation2)
  internal
  pure
  returns (uint16)
{
  return (generation1 + generation2) / 2 + 1;
}

function _mixGenes(uint256 genes1, uint256 genes2)
  internal
  view
  returns (uint256)
{
  // example genes: 20203001003511
  // in 7 parts: 20 20 300 100 35 1 1
  uint256 mixedGenes;
  uint16[7] memory mixedGenesParts;
  uint8 index = 6;

  // the binary representation of this random number (0-255) decides which parts to take from genes1 and which from genes2
  uint8 randomBinary = uint8(block.timestamp);
  uint8 maskBinary = 1;
  uint16 factor;

  // inherit 'mixedGenesParts' from parents 'genes1' and 'genes2'
  for (uint8 i = 0; i <= 6; i++) {
    if (index == 3 || index == 2) {
      factor = 1000;
    } else if (index == 6 || index == 5) {
      factor = 10;
    } else {
      factor = 100;
    }

    if ((randomBinary & maskBinary) == 0) {
      mixedGenesParts[index] = uint16(genes1 % factor);
    } else {
      mixedGenesParts[index] = uint16(genes2 % factor);
    }

    if (i != 6) {
      genes1 /= factor;
      genes2 /= factor;
      maskBinary *= 2;
      index--;
    }
  }

  // add random value for one random genes part
  uint8 randomPart = randomBinary % 7;
  uint16 randomPartValue;
  if (randomPart == 0 || randomPart == 1) {
    randomPartValue = 10 + (randomBinary % 81);
  } else if (randomPart == 2) {
    randomPartValue = 100 + randomBinary;
  } else if (randomPart == 3) {
    randomPartValue = uint16(10**(randomBinary % 3));
  } else if (randomPart == 4) {
    randomPartValue = 10 + (randomBinary % 46);
  } else if (randomPart == 5 || randomPart == 6) {
    randomPartValue = randomBinary % 4;
  }
  mixedGenesParts[randomPart] = randomPartValue;

  // assemble 'mixedGenes'
  for (uint8 i = 0; i <= 6; i++) {
    mixedGenes += mixedGenesParts[i];
    if (i != 6) {
      if (i == 1 || i == 2) {
        factor = 1000;
      } else if (i == 4 || i == 5) {
        factor = 10;
      } else {
        factor = 100;
      }
      mixedGenes *= factor;
    }
  }

  return mixedGenes;
}

function _createKitty(
  uint256 mumId,
  uint256 dadId,
  uint256 generation,
  uint256 genes,
  address owner
) internal {
  Kitty memory newKitty = Kitty({
    genes: genes,
    birthTime: uint64(block.timestamp),
    mumId: uint32(mumId),
    dadId: uint32(dadId),
    generation: uint16(generation)
  });
  _kitties.push(newKitty);

  uint256 newKittyId = _kitties.length - 1;
  require(newKittyId == uint256(uint32(newKittyId)));
  emit Birth(
    owner,
    newKittyId,
    uint256(newKitty.mumId),
    uint256(newKitty.dadId),
    newKitty.genes
  );

  _safeMint(owner, newKittyId);
}
}

2 Likes

Got it from here:

_mixDna function

function _mixDna(uint256 _dadDna, uint256 _mumDna)

    internal

    view

    returns (uint256)

{

    uint256[8] memory geneArray;

    //pseudo-random: Not used for betting and monetary stuff

    //binary 8bit between 00000000 to 11111111

    uint8 random = uint8(

        uint256(

            keccak256(abi.encodePacked(block.timestamp, block.difficulty))

        ) % 255

    );

    //1, 2, 4, 8, 16, 32, 64, 128, loop through 8 times

    //values of the 8 numbers above in binary

    //00000001, 00000010, 00000100, 00001000,

    //00010000, 00100000, 01000000, 10000000

    //bitwise operator &

    uint256 i = 1;

    uint256 index = 7;

    for (i = 1; i <= 128; i *= 2) {

        if (random & i != 0) {

            geneArray[index] = uint8(_mumDna % 100); //last pair

        } else {

            geneArray[index] = uint8(_dadDna % 100);

        }

        //now remove last pair from dna

        _mumDna /= 100;

        _dadDna /= 100;

        //reduce index to set position to previous (e.g. from 7 to 6)

        index--;

    }

    //create DNA into a full number

    uint256 newGene;

    for (i = 0; i < 8; i++) {

        newGene += geneArray[i]; //add first pair to mewGene

        if (i != 7) {

            //to not add 2 zeroes after the last pair

            newGene *= 100; //adds two zeroes (00), at the end of each pair

        }

    }

    return newGene;

}
1 Like

Mixing DNA randomness.

function _mixDna(uint256 dadDNA, uint256 momDNA) internal view returns (uint256) {
        {

    uint256[8] memory geneArray;

    //pseudo-random: Not used for betting and monetary stuff

    //binary 8bit between 00000000 to 11111111

    uint8 random = uint8(

        uint256(

            keccak256(abi.encodePacked(block.timestamp, block.difficulty))

        ) % 255

    );

    uint256 i = 1;

    uint256 index = 7;

    for (i = 1; i <= 128; i *= 2) {

        if (random & i != 0) {

            geneArray[index] = uint8(momDNA % 100); //last pair

        } else {

            geneArray[index] = uint8(dadDNA % 100);

        }

        //now remove last pair from dna

        momDNA /= 100;

        dadDNA /= 100;

        //reduce index to set position to previous (e.g. from 7 to 6)

        index--;

    }

    //create DNA into a full number

    uint256 newGene;

    for (i = 0; i < 8; i++) {

        newGene += geneArray[i]; //add first pair to mewGene

        if (i != 7) {

            //to not add 2 zeroes after the last pair

            newGene *= 100; //adds two zeroes (00), at the end of each pair

        }

    }

    return newGene;

}
    }

Hiya!
From the below code, I’m getting an error in Remix -

The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.

//SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.0;

contract Test{
    
     function _mixDNA(uint dadDNA,uint mumDNA) public view returns(uint){
      uint[8] memory geneArray;
      uint8 random = uint8(block.timestamp % 256); //0-255
      uint index = 7;

      for(uint i = 1 ; i <= 128 ; i = i*2){
       if(random & i != 0){
         geneArray[index] = mumDNA % 100;
       }
       else{
         geneArray[index] = dadDNA % 100;

       }
       mumDNA = mumDNA / 100;
       dadDNA = dadDNA / 100;
       index = index-1;
      }

      uint newGene = 0;
      for(uint i = 0 ; i < 8 ; i++){
         newGene = newGene + geneArray[i];
         if(i != 7){
           newGene = newGene * 100;
         } 
      }
      return newGene;
   }
}

//1122334455667788,8877665544332211

Still getting the same error with this function header-

     function _mixDNA(uint dadDNA,uint mumDNA) public payable returns(uint){

But the thing is…with compiler version 0.5.12 it’s working fine.
@kenn.eth how can I resolve this one.

Edit: That’s the error in the truffle

Uncaught Error: Returned error: VM Exception while processing transaction: revert
    at evalmachine.<anonymous>:0:10
    at sigintHandlersWrap (vm.js:273:12)
    at Script.runInContext (vm.js:140:14)
    at runScript (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\console.js:329:1)    
    at Console.interpret (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\console.js:344:1)
    at bound (domain.js:413:15)
    at REPLServer.runBound [as eval] (domain.js:424:12)
    at REPLServer.onLine (repl.js:817:10)
    at REPLServer.emit (events.js:315:20)
    at REPLServer.EventEmitter.emit (domain.js:467:12)
    at REPLServer.Interface._onLine (readline.js:337:10)
    at REPLServer.Interface._line (readline.js:666:8)
    at REPLServer.Interface._ttyWrite (readline.js:1010:14)
    at REPLServer.self._ttyWrite (repl.js:907:9) {
  data: {
    '0x582bdafd2952d384db69a303cbfa0d88a3a90ecb344bcd9a7babe11d5bcb1792': {
      error: 'revert',
      program_counter: 12546,
      return: '0x4e487b710000000000000000000000000000000000000000000000000000000000000011'
    },
    stack: 'RuntimeError: VM Exception while processing transaction: revert\n' +
      '    at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n' +
      '    at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n' +
      '    at runMicrotasks (<anonymous>)\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:93:5)',
    name: 'RuntimeError'
  },
  hijackedStack: 'Error: Returned error: VM Exception while processing transaction: revert\n' +
    '    at Object.ErrorResponse (C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\web3-core-helpers\\lib\\errors.js:28:1)\n' +
    '    at C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\web3\\node_modules\\web3-core-requestmanager\\lib\\index.js:303:1\n' +
    '    at C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\packages\\provider\\wrapper.js:107:1\n' +
    '    at XMLHttpRequest.request.onreadystatechange (C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\web3\\node_modules\\web3-providers-http\\lib\\index.js:98:1)\n' +
    '    at XMLHttpRequestEventTarget.dispatchEvent (C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\xhr2-cookies\\dist\\xml-http-request-event-target.js:34:1)\n' +
    '    at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._setReadyState (C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\xhr2-cookies\\dist\\xml-http-request.js:208:1)\n' +
    '    at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._onHttpResponseEnd (C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\xhr2-cookies\\dist\\xml-http-request.js:318:1)\n' +
    '    at IncomingMessage.<anonymous> (C:\\Users\\HP\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\xhr2-cookies\\dist\\xml-http-request.js:289:47)\n' +
    '    at IncomingMessage.emit (events.js:327:22)\n' +
    '    at IncomingMessage.EventEmitter.emit (domain.js:529:15)\n' +
    '    at endReadableNT (internal/streams/readable.js:1327:12)\n' +
    '    at processTicksAndRejections (internal/process/task_queues.js:80:21)'
}
2 Likes

Assignment:

//SPDX-License-Identifier: UNLICENSED
pragma solidity 0.5.12;

contract Test{
    
     function _mixDNA(uint dadDNA,uint mumDNA) public view returns(uint){
      uint[8] memory geneArray;
      uint8 random = uint8(block.timestamp % 256); //0-255
      uint index = 7;

      for(uint i = 1 ; i <= 128 ; i = i*2){
       if(random & i != 0){
         geneArray[index] = mumDNA % 100;
       }
       else{
         geneArray[index] = dadDNA % 100;

       }
       mumDNA = mumDNA / 100;
       dadDNA = dadDNA / 100;
       index = index-1;
      }
      
      for(uint i = 0 ; i < 4 ; i++){
          uint8 pos = uint8(block.timestamp % 8); //0-7
          uint8 newRandom = uint8(block.timestamp % 100);//0-99
          geneArray[pos] = newRandom;
      }
      
      uint newGene = 0;
      for(uint i = 0 ; i < 8 ; i++){
         newGene = newGene + geneArray[i];
         if(i != 7){
           newGene = newGene * 100;
         } 
      }
      return newGene;
   }
}

//1122334455667788,8877665544332211

Hey @tanu_g, hope you are well.

I have managed to run your _mixDNA function with solidity 0.8.0, the problem is on the amount of steps for the loop iteration with the variable i. For a 16digits DNA like yours, the amount of iterations might not need to be the same, (instead of i <= 128, yours work with i <= 64).

The problem comes from the index variable, the last iteration will fail cuz index should be always a positive number (uint), but for each iteration it will decrease one and at the last iteration it will run into a negative number.

Carlos Z

3 Likes